aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS5
-rw-r--r--Documentation/ABI/testing/sysfs-class-devfreq44
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power31
-rw-r--r--Documentation/ABI/testing/sysfs-devices-sun14
-rw-r--r--Documentation/DocBook/uio-howto.tmpl56
-rw-r--r--Documentation/IRQ-domain.txt34
-rw-r--r--Documentation/acpi/enumeration.txt227
-rw-r--r--Documentation/devicetree/bindings/arm/atmel-at91.txt6
-rw-r--r--Documentation/devicetree/bindings/arm/davinci/nand.txt37
-rw-r--r--Documentation/devicetree/bindings/arm/l2cc.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/imx23-clock.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/imx28-clock.txt4
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt42
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-stmpe.txt18
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio.txt36
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio_atmel.txt5
-rw-r--r--Documentation/devicetree/bindings/gpio/spear_spics.txt50
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-at91.txt (renamed from Documentation/devicetree/bindings/i2c/atmel-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-davinci.txt (renamed from Documentation/devicetree/bindings/i2c/davinci.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-gpio.txt (renamed from Documentation/devicetree/bindings/i2c/gpio-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-imx.txt (renamed from Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-mpc.txt (renamed from Documentation/devicetree/bindings/i2c/fsl-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-mux.txt (renamed from Documentation/devicetree/bindings/i2c/mux.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt18
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-nomadik.txt (renamed from Documentation/devicetree/bindings/i2c/nomadik.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-octeon.txt (renamed from Documentation/devicetree/bindings/i2c/cavium-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-omap.txt (renamed from Documentation/devicetree/bindings/i2c/omap-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-pnx.txt (renamed from Documentation/devicetree/bindings/i2c/pnx.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt (renamed from Documentation/devicetree/bindings/i2c/ce4100-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-pxa.txt (renamed from Documentation/devicetree/bindings/i2c/mrvl-i2c.txt)18
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt (renamed from Documentation/devicetree/bindings/i2c/samsung-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-sirf.txt (renamed from Documentation/devicetree/bindings/i2c/sirf-i2c.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-versatile.txt (renamed from Documentation/devicetree/bindings/i2c/arm-versatile.txt)0
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-xiic.txt (renamed from Documentation/devicetree/bindings/i2c/xiic.txt)0
-rw-r--r--Documentation/devicetree/bindings/leds/common.txt23
-rw-r--r--Documentation/devicetree/bindings/leds/leds-gpio.txt (renamed from Documentation/devicetree/bindings/gpio/led.txt)14
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc.txt8
-rw-r--r--Documentation/devicetree/bindings/mmc/samsung-sdhci.txt20
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt (renamed from Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt)0
-rw-r--r--Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt1
-rw-r--r--Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt23
-rw-r--r--Documentation/devicetree/bindings/net/mdio-gpio.txt9
-rw-r--r--Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt141
-rw-r--r--Documentation/devicetree/bindings/rtc/orion-rtc.txt18
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt6
-rw-r--r--Documentation/devicetree/usage-model.txt2
-rw-r--r--Documentation/firmware_class/README12
-rw-r--r--Documentation/gpio.txt42
-rw-r--r--Documentation/hwmon/ads782846
-rw-r--r--Documentation/hwmon/coretemp2
-rw-r--r--Documentation/hwmon/da905547
-rw-r--r--Documentation/kbuild/makefiles.txt15
-rw-r--r--Documentation/mmc/mmc-dev-attrs.txt7
-rw-r--r--Documentation/networking/vxlan.txt4
-rw-r--r--Documentation/pinctrl.txt7
-rw-r--r--Documentation/power/pm_qos_interface.txt2
-rw-r--r--Documentation/zh_CN/arm/kernel_user_helpers.txt284
-rw-r--r--Documentation/zh_CN/arm64/memory.txt14
-rw-r--r--MAINTAINERS45
-rw-r--r--Makefile8
-rw-r--r--arch/alpha/kernel/osf_sys.c6
-rw-r--r--arch/arm/Kconfig6
-rw-r--r--arch/arm/Makefile4
-rw-r--r--arch/arm/boot/Makefile12
-rw-r--r--arch/arm/boot/compressed/head.S14
-rw-r--r--arch/arm/boot/dts/Makefile56
-rw-r--r--arch/arm/boot/dts/animeo_ip.dts178
-rw-r--r--arch/arm/boot/dts/at91rm9200.dtsi349
-rw-r--r--arch/arm/boot/dts/at91rm9200ek.dts79
-rw-r--r--arch/arm/boot/dts/at91sam9260.dtsi295
-rw-r--r--arch/arm/boot/dts/at91sam9263.dtsi299
-rw-r--r--arch/arm/boot/dts/at91sam9263ek.dts29
-rw-r--r--arch/arm/boot/dts/at91sam9g15.dtsi28
-rw-r--r--arch/arm/boot/dts/at91sam9g15ek.dts16
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_2mmc.dts26
-rw-r--r--arch/arm/boot/dts/at91sam9g20ek_common.dtsi30
-rw-r--r--arch/arm/boot/dts/at91sam9g25.dtsi28
-rw-r--r--arch/arm/boot/dts/at91sam9g25ek.dts49
-rw-r--r--arch/arm/boot/dts/at91sam9g35.dtsi28
-rw-r--r--arch/arm/boot/dts/at91sam9g35ek.dts16
-rw-r--r--arch/arm/boot/dts/at91sam9g45.dtsi301
-rw-r--r--arch/arm/boot/dts/at91sam9m10g45ek.dts48
-rw-r--r--arch/arm/boot/dts/at91sam9n12.dtsi225
-rw-r--r--arch/arm/boot/dts/at91sam9n12ek.dts22
-rw-r--r--arch/arm/boot/dts/at91sam9x25.dtsi49
-rw-r--r--arch/arm/boot/dts/at91sam9x25ek.dts16
-rw-r--r--arch/arm/boot/dts/at91sam9x35.dtsi28
-rw-r--r--arch/arm/boot/dts/at91sam9x35ek.dts16
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi270
-rw-r--r--arch/arm/boot/dts/at91sam9x5ek.dtsi101
-rw-r--r--arch/arm/boot/dts/pm9g45.dts165
-rw-r--r--arch/arm/boot/dts/spear1310-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear1310.dtsi27
-rw-r--r--arch/arm/boot/dts/spear1340-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear1340.dtsi26
-rw-r--r--arch/arm/boot/dts/spear310.dtsi22
-rw-r--r--arch/arm/boot/dts/spear320-evb.dts4
-rw-r--r--arch/arm/boot/dts/spear320.dtsi23
-rw-r--r--arch/arm/boot/dts/tegra20-seaboard.dts4
-rw-r--r--arch/arm/common/timer-sp.c2
-rw-r--r--arch/arm/configs/at91_dt_defconfig1
-rw-r--r--arch/arm/include/asm/hardware/sp810.h2
-rw-r--r--arch/arm/include/asm/io.h2
-rw-r--r--arch/arm/include/asm/prom.h2
-rw-r--r--arch/arm/mach-at91/Kconfig9
-rw-r--r--arch/arm/mach-at91/Makefile1
-rw-r--r--arch/arm/mach-at91/at91rm9200.c22
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c63
-rw-r--r--arch/arm/mach-at91/at91sam9260.c8
-rw-r--r--arch/arm/mach-at91/at91sam9261.c4
-rw-r--r--arch/arm/mach-at91/at91sam9263.c11
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c12
-rw-r--r--arch/arm/mach-at91/at91sam9n12.c16
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c4
-rw-r--r--arch/arm/mach-at91/at91sam9x5.c21
-rw-r--r--arch/arm/mach-at91/board-dt.c2
-rw-r--r--arch/arm/mach-at91/board-rm9200-dt.c57
-rw-r--r--arch/arm/mach-at91/generic.h1
-rw-r--r--arch/arm/mach-at91/gpio.c190
-rw-r--r--arch/arm/mach-at91/include/mach/board.h10
-rw-r--r--arch/arm/mach-at91/setup.c20
-rw-r--r--arch/arm/mach-at91/soc.h12
-rw-r--r--arch/arm/mach-davinci/dm644x.c3
-rw-r--r--arch/arm/mach-dove/include/mach/pm.h2
-rw-r--r--arch/arm/mach-dove/irq.c14
-rw-r--r--arch/arm/mach-exynos/dma.c3
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h1
-rw-r--r--arch/arm/mach-integrator/impd1.c69
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c1
-rw-r--r--arch/arm/mach-ixp4xx/common.c13
-rw-r--r--arch/arm/mach-ixp4xx/goramo_mlr.c3
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/debug-macro.S4
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h46
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/qmgr.h12
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_npe.c9
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_qmgr.c12
-rw-r--r--arch/arm/mach-kirkwood/pcie.c11
-rw-r--r--arch/arm/mach-nomadik/board-nhk8815.c3
-rw-r--r--arch/arm/mach-nomadik/cpu-8815.c2
-rw-r--r--arch/arm/mach-nomadik/i2c-8815nhk.c3
-rw-r--r--arch/arm/mach-omap2/board-igep0020.c5
-rw-r--r--arch/arm/mach-omap2/common-board-devices.c34
-rw-r--r--arch/arm/mach-omap2/twl-common.c1
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c2
-rw-r--r--arch/arm/mach-u300/core.c5
-rw-r--r--arch/arm/mach-u300/include/mach/irqs.h126
-rw-r--r--arch/arm/mach-ux500/board-mop500-audio.c3
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c3
-rw-r--r--arch/arm/mach-ux500/board-mop500.c2
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c12
-rw-r--r--arch/arm/mach-ux500/devices-common.c3
-rw-r--r--arch/arm/mach-ux500/devices-common.h8
-rw-r--r--arch/arm/mach-vexpress/v2m.c2
-rw-r--r--arch/arm/mm/mmap.c2
-rw-r--r--arch/arm/mm/proc-v6.S2
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio-nomadik.h102
-rw-r--r--arch/arm/plat-omap/i2c.c21
-rw-r--r--arch/arm/plat-omap/include/plat/mmc.h1
-rw-r--r--arch/arm/plat-s3c24xx/dma.c9
-rw-r--r--arch/arm/plat-spear/Kconfig1
-rw-r--r--arch/arm64/Makefile17
-rw-r--r--arch/arm64/boot/Makefile5
-rw-r--r--arch/arm64/boot/dts/.gitignore1
-rw-r--r--arch/arm64/boot/dts/Makefile5
-rw-r--r--arch/arm64/include/asm/unistd32.h2
-rw-r--r--arch/c6x/Makefile2
-rw-r--r--arch/c6x/boot/Makefile20
-rw-r--r--arch/c6x/boot/dts/Makefile20
-rw-r--r--arch/c6x/boot/dts/linked_dtb.S2
-rw-r--r--arch/c6x/boot/linked_dtb.S2
-rw-r--r--arch/c6x/include/asm/setup.h33
-rw-r--r--arch/c6x/include/uapi/asm/Kbuild2
-rw-r--r--arch/c6x/include/uapi/asm/kvm_para.h1
-rw-r--r--arch/c6x/include/uapi/asm/setup.h33
-rw-r--r--arch/c6x/kernel/entry.S5
-rw-r--r--arch/ia64/include/asm/device.h3
-rw-r--r--arch/ia64/include/asm/io.h2
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/efi.c2
-rw-r--r--arch/m68k/include/asm/signal.h6
-rw-r--r--arch/microblaze/Makefile2
-rw-r--r--arch/microblaze/boot/Makefile19
-rw-r--r--arch/microblaze/boot/dts/Makefile22
-rw-r--r--arch/microblaze/boot/dts/linked_dtb.S2
-rw-r--r--arch/microblaze/boot/linked_dtb.S3
-rw-r--r--arch/microblaze/kernel/signal.c2
-rw-r--r--arch/microblaze/pci/pci-common.c4
-rw-r--r--arch/mips/cavium-octeon/Makefile3
-rw-r--r--arch/mips/include/asm/hugetlb.h12
-rw-r--r--arch/mips/kernel/cpu-probe.c1
-rw-r--r--arch/mips/kernel/entry.S7
-rw-r--r--arch/mips/kernel/scall64-n32.S6
-rw-r--r--arch/mips/kernel/setup.c26
-rw-r--r--arch/mips/lantiq/dts/Makefile3
-rw-r--r--arch/mips/lib/mips-atomic.c8
-rw-r--r--arch/mips/mm/tlb-r4k.c18
-rw-r--r--arch/mips/netlogic/dts/Makefile3
-rw-r--r--arch/mips/pci/pci.c2
-rw-r--r--arch/openrisc/Makefile2
-rw-r--r--arch/openrisc/boot/dts/Makefile (renamed from arch/openrisc/boot/Makefile)5
-rw-r--r--arch/openrisc/kernel/signal.c6
-rw-r--r--arch/parisc/kernel/signal32.c6
-rw-r--r--arch/parisc/kernel/sys_parisc.c2
-rw-r--r--arch/parisc/kernel/syscall_table.S2
-rw-r--r--arch/powerpc/boot/dts/mpc5200b.dtsi6
-rw-r--r--arch/powerpc/boot/dts/o2d.dtsi6
-rw-r--r--arch/powerpc/boot/dts/pcm030.dts7
-rw-r--r--arch/powerpc/kernel/pci-common.c4
-rw-r--r--arch/powerpc/kernel/pci_64.c4
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c9
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pe.c2
-rw-r--r--arch/powerpc/platforms/pseries/msi.c3
-rw-r--r--arch/powerpc/platforms/pseries/processor_idle.c4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c3
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c2
-rw-r--r--arch/powerpc/sysdev/scom.c2
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/score/kernel/signal.c7
-rw-r--r--arch/sh/drivers/pci/pci.c2
-rw-r--r--arch/sh/include/asm/io.h2
-rw-r--r--arch/sh/kernel/signal_64.c6
-rw-r--r--arch/sh/mm/mmap.c2
-rw-r--r--arch/sparc/boot/piggyback.c12
-rw-r--r--arch/sparc/include/asm/prom.h5
-rw-r--r--arch/sparc/kernel/pci_impl.h2
-rw-r--r--arch/sparc/kernel/signal_64.c4
-rw-r--r--arch/sparc/kernel/sys32.S2
-rw-r--r--arch/sparc/kernel/syscalls.S14
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/um/kernel/exec.c3
-rw-r--r--arch/unicore32/kernel/pci.c2
-rw-r--r--arch/x86/boot/compressed/eboot.c2
-rw-r--r--arch/x86/boot/header.S3
-rw-r--r--arch/x86/include/asm/Kbuild3
-rw-r--r--arch/x86/include/asm/device.h3
-rw-r--r--arch/x86/include/asm/fpu-internal.h15
-rw-r--r--arch/x86/include/asm/ptrace.h15
-rw-r--r--arch/x86/kernel/acpi/boot.c6
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/cpu/amd.c14
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c31
-rw-r--r--arch/x86/kernel/entry_64.S14
-rw-r--r--arch/x86/kernel/head_32.S9
-rw-r--r--arch/x86/kernel/microcode_amd.c8
-rw-r--r--arch/x86/kernel/ptrace.c37
-rw-r--r--arch/x86/kernel/smpboot.c5
-rw-r--r--arch/x86/kvm/emulate.c3
-rw-r--r--arch/x86/mm/tlb.c2
-rw-r--r--arch/x86/pci/ce4100.c13
-rw-r--r--arch/x86/platform/ce4100/ce4100.c24
-rw-r--r--block/blk-exec.c8
-rw-r--r--drivers/acpi/Kconfig6
-rw-r--r--drivers/acpi/Makefile6
-rw-r--r--drivers/acpi/acpi_i2c.c103
-rw-r--r--drivers/acpi/acpi_memhotplug.c193
-rw-r--r--drivers/acpi/acpi_pad.c8
-rw-r--r--drivers/acpi/acpi_platform.c104
-rw-r--r--drivers/acpi/acpica/Makefile3
-rw-r--r--drivers/acpi/acpica/acdebug.h94
-rw-r--r--drivers/acpi/acpica/acdispat.h11
-rw-r--r--drivers/acpi/acpica/acevents.h6
-rw-r--r--drivers/acpi/acpica/acglobal.h73
-rw-r--r--drivers/acpi/acpica/aclocal.h16
-rw-r--r--drivers/acpi/acpica/acmacros.h163
-rw-r--r--drivers/acpi/acpica/acobject.h7
-rw-r--r--drivers/acpi/acpica/acopcode.h6
-rw-r--r--drivers/acpi/acpica/acparser.h3
-rw-r--r--drivers/acpi/acpica/acpredef.h11
-rw-r--r--drivers/acpi/acpica/acstruct.h2
-rw-r--r--drivers/acpi/acpica/acutils.h58
-rw-r--r--drivers/acpi/acpica/amlresrc.h1
-rw-r--r--drivers/acpi/acpica/dscontrol.c2
-rw-r--r--drivers/acpi/acpica/dsfield.c2
-rw-r--r--drivers/acpi/acpica/dsmethod.c6
-rw-r--r--drivers/acpi/acpica/dsmthdat.c14
-rw-r--r--drivers/acpi/acpica/dsobject.c6
-rw-r--r--drivers/acpi/acpica/dsopcode.c3
-rw-r--r--drivers/acpi/acpica/dsutils.c33
-rw-r--r--drivers/acpi/acpica/dswexec.c10
-rw-r--r--drivers/acpi/acpica/dswload2.c4
-rw-r--r--drivers/acpi/acpica/dswstate.c26
-rw-r--r--drivers/acpi/acpica/evgpe.c20
-rw-r--r--drivers/acpi/acpica/evgpeblk.c3
-rw-r--r--drivers/acpi/acpica/evgpeutil.c3
-rw-r--r--drivers/acpi/acpica/evrgnini.c7
-rw-r--r--drivers/acpi/acpica/evxface.c2
-rw-r--r--drivers/acpi/acpica/evxfgpe.c13
-rw-r--r--drivers/acpi/acpica/exconvrt.c4
-rw-r--r--drivers/acpi/acpica/excreate.c9
-rw-r--r--drivers/acpi/acpica/exdebug.c10
-rw-r--r--drivers/acpi/acpica/exdump.c20
-rw-r--r--drivers/acpi/acpica/exfield.c4
-rw-r--r--drivers/acpi/acpica/exfldio.c15
-rw-r--r--drivers/acpi/acpica/exmisc.c5
-rw-r--r--drivers/acpi/acpica/exmutex.c9
-rw-r--r--drivers/acpi/acpica/exnames.c9
-rw-r--r--drivers/acpi/acpica/exoparg1.c11
-rw-r--r--drivers/acpi/acpica/exoparg2.c2
-rw-r--r--drivers/acpi/acpica/exoparg3.c3
-rw-r--r--drivers/acpi/acpica/exoparg6.c5
-rw-r--r--drivers/acpi/acpica/exprep.c13
-rw-r--r--drivers/acpi/acpica/exregion.c3
-rw-r--r--drivers/acpi/acpica/exresnte.c9
-rw-r--r--drivers/acpi/acpica/exresolv.c3
-rw-r--r--drivers/acpi/acpica/exresop.c8
-rw-r--r--drivers/acpi/acpica/exstore.c4
-rw-r--r--drivers/acpi/acpica/exstoren.c11
-rw-r--r--drivers/acpi/acpica/exstorob.c5
-rw-r--r--drivers/acpi/acpica/exsystem.c9
-rw-r--r--drivers/acpi/acpica/exutils.c5
-rw-r--r--drivers/acpi/acpica/hwacpi.c3
-rw-r--r--drivers/acpi/acpica/hwgpe.c4
-rw-r--r--drivers/acpi/acpica/hwpci.c4
-rw-r--r--drivers/acpi/acpica/hwregs.c1
-rw-r--r--drivers/acpi/acpica/hwtimer.c6
-rw-r--r--drivers/acpi/acpica/hwvalid.c1
-rw-r--r--drivers/acpi/acpica/hwxface.c1
-rw-r--r--drivers/acpi/acpica/hwxfsleep.c12
-rw-r--r--drivers/acpi/acpica/nsaccess.c7
-rw-r--r--drivers/acpi/acpica/nsalloc.c4
-rw-r--r--drivers/acpi/acpica/nsdump.c10
-rw-r--r--drivers/acpi/acpica/nsinit.c4
-rw-r--r--drivers/acpi/acpica/nsload.c10
-rw-r--r--drivers/acpi/acpica/nsnames.c2
-rw-r--r--drivers/acpi/acpica/nsobject.c8
-rw-r--r--drivers/acpi/acpica/nsparse.c8
-rw-r--r--drivers/acpi/acpica/nssearch.c17
-rw-r--r--drivers/acpi/acpica/nsutils.c18
-rw-r--r--drivers/acpi/acpica/nswalk.c10
-rw-r--r--drivers/acpi/acpica/nsxfeval.c20
-rw-r--r--drivers/acpi/acpica/nsxfname.c66
-rw-r--r--drivers/acpi/acpica/nsxfobj.c4
-rw-r--r--drivers/acpi/acpica/psargs.c8
-rw-r--r--drivers/acpi/acpica/psloop.c61
-rw-r--r--drivers/acpi/acpica/psopcode.c29
-rw-r--r--drivers/acpi/acpica/psparse.c13
-rw-r--r--drivers/acpi/acpica/psutils.c4
-rw-r--r--drivers/acpi/acpica/rscalc.c14
-rw-r--r--drivers/acpi/acpica/rslist.c4
-rw-r--r--drivers/acpi/acpica/tbfind.c2
-rw-r--r--drivers/acpi/acpica/tbinstal.c2
-rw-r--r--drivers/acpi/acpica/tbutils.c2
-rw-r--r--drivers/acpi/acpica/tbxface.c4
-rw-r--r--drivers/acpi/acpica/tbxfload.c2
-rw-r--r--drivers/acpi/acpica/tbxfroot.c3
-rw-r--r--drivers/acpi/acpica/utcache.c323
-rw-r--r--drivers/acpi/acpica/utclib.c749
-rw-r--r--drivers/acpi/acpica/utdebug.c37
-rw-r--r--drivers/acpi/acpica/utids.c104
-rw-r--r--drivers/acpi/acpica/utmath.c2
-rw-r--r--drivers/acpi/acpica/utmisc.c150
-rw-r--r--drivers/acpi/acpica/utmutex.c14
-rw-r--r--drivers/acpi/acpica/utobject.c8
-rw-r--r--drivers/acpi/acpica/utstate.c2
-rw-r--r--drivers/acpi/acpica/uttrack.c692
-rw-r--r--drivers/acpi/acpica/utxface.c5
-rw-r--r--drivers/acpi/acpica/utxferror.c2
-rw-r--r--drivers/acpi/apei/ghes.c4
-rw-r--r--drivers/acpi/battery.c77
-rw-r--r--drivers/acpi/bus.c21
-rw-r--r--drivers/acpi/container.c27
-rw-r--r--drivers/acpi/device_pm.c668
-rw-r--r--drivers/acpi/dock.c56
-rw-r--r--drivers/acpi/ec.c97
-rw-r--r--drivers/acpi/glue.c56
-rw-r--r--drivers/acpi/hed.c4
-rw-r--r--drivers/acpi/internal.h11
-rw-r--r--drivers/acpi/osl.c22
-rw-r--r--drivers/acpi/pci_irq.c15
-rw-r--r--drivers/acpi/pci_root.c2
-rw-r--r--drivers/acpi/power.c2
-rw-r--r--drivers/acpi/proc.c11
-rw-r--r--drivers/acpi/processor_driver.c74
-rw-r--r--drivers/acpi/processor_idle.c57
-rw-r--r--drivers/acpi/resource.c526
-rw-r--r--drivers/acpi/scan.c154
-rw-r--r--drivers/acpi/sleep.c535
-rw-r--r--drivers/acpi/sysfs.c4
-rw-r--r--drivers/acpi/thermal.c34
-rw-r--r--drivers/acpi/utils.c38
-rw-r--r--drivers/acpi/video.c14
-rw-r--r--drivers/acpi/video_detect.c8
-rw-r--r--drivers/ata/ahci_platform.c2
-rw-r--r--drivers/ata/libata-acpi.c11
-rw-r--r--drivers/ata/libata-core.c4
-rw-r--r--drivers/ata/libata-scsi.c2
-rw-r--r--drivers/ata/pata_arasan_cf.c8
-rw-r--r--drivers/ata/sata_highbank.c4
-rw-r--r--drivers/ata/sata_svw.c35
-rw-r--r--drivers/atm/ambassador.c1
-rw-r--r--drivers/base/Kconfig7
-rw-r--r--drivers/base/attribute_container.c2
-rw-r--r--drivers/base/bus.c14
-rw-r--r--drivers/base/core.c10
-rw-r--r--drivers/base/devres.c4
-rw-r--r--drivers/base/dma-contiguous.c24
-rw-r--r--drivers/base/firmware_class.c52
-rw-r--r--drivers/base/platform.c30
-rw-r--r--drivers/base/power/clock_ops.c6
-rw-r--r--drivers/base/power/domain.c11
-rw-r--r--drivers/base/power/opp.c44
-rw-r--r--drivers/base/power/power.h6
-rw-r--r--drivers/base/power/qos.c323
-rw-r--r--drivers/base/power/sysfs.c94
-rw-r--r--drivers/block/aoe/aoecmd.c2
-rw-r--r--drivers/block/floppy.c5
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c18
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h6
-rw-r--r--drivers/char/agp/ali-agp.c4
-rw-r--r--drivers/char/agp/amd-k7-agp.c4
-rw-r--r--drivers/char/agp/amd64-agp.c2
-rw-r--r--drivers/char/agp/ati-agp.c4
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/agp/i460-agp.c2
-rw-r--r--drivers/char/agp/intel-agp.c2
-rw-r--r--drivers/char/agp/nvidia-agp.c2
-rw-r--r--drivers/char/agp/sgi-agp.c2
-rw-r--r--drivers/char/agp/sis-agp.c8
-rw-r--r--drivers/char/agp/sworks-agp.c2
-rw-r--r--drivers/char/agp/uninorth-agp.c4
-rw-r--r--drivers/char/agp/via-agp.c4
-rw-r--r--drivers/char/hpet.c5
-rw-r--r--drivers/char/hw_random/Kconfig6
-rw-r--r--drivers/char/hw_random/atmel-rng.c2
-rw-r--r--drivers/char/hw_random/bcm63xx-rng.c2
-rw-r--r--drivers/char/hw_random/exynos-rng.c2
-rw-r--r--drivers/char/hw_random/ixp4xx-rng.c5
-rw-r--r--drivers/char/hw_random/n2-drv.c4
-rw-r--r--drivers/char/hw_random/pasemi-rng.c2
-rw-r--r--drivers/char/hw_random/picoxcell-rng.c2
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c2
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c2
-rw-r--r--drivers/char/hw_random/virtio-rng.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c32
-rw-r--r--drivers/char/mbcs.c2
-rw-r--r--drivers/char/mem.c10
-rw-r--r--drivers/char/pc8736x_gpio.c3
-rw-r--r--drivers/char/ps3flash.c2
-rw-r--r--drivers/char/raw.c2
-rw-r--r--drivers/char/sonypi.c14
-rw-r--r--drivers/char/tb0219.c6
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c6
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c6
-rw-r--r--drivers/char/tpm/tpm_infineon.c6
-rw-r--r--drivers/char/tpm/tpm_tis.c6
-rw-r--r--drivers/char/virtio_console.c2
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c14
-rw-r--r--drivers/clk/Kconfig16
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-bcm2835.c8
-rw-r--r--drivers/clk/clk-fixed-rate.c2
-rw-r--r--drivers/clk/clk-max77686.c6
-rw-r--r--drivers/clk/clk-prima2.c84
-rw-r--r--drivers/clk/clk-twl6040.c126
-rw-r--r--drivers/clk/clk-vt8500.c18
-rw-r--r--drivers/clk/clk-wm831x.c40
-rw-r--r--drivers/clk/clk.c154
-rw-r--r--drivers/clk/mxs/clk-imx23.c6
-rw-r--r--drivers/clk/mxs/clk-imx28.c10
-rw-r--r--drivers/clk/spear/clk-aux-synth.c3
-rw-r--r--drivers/clk/spear/clk-vco-pll.c2
-rw-r--r--drivers/clk/spear/clk.c3
-rw-r--r--drivers/clk/spear/spear1310_clock.c106
-rw-r--r--drivers/clk/spear/spear1340_clock.c237
-rw-r--r--drivers/clk/spear/spear3xx_clock.c154
-rw-r--r--drivers/clk/spear/spear6xx_clock.c13
-rw-r--r--drivers/clk/ux500/Makefile3
-rw-r--r--drivers/clk/ux500/abx500-clk.c73
-rw-r--r--drivers/clk/ux500/clk-prcmu.c72
-rw-r--r--drivers/clk/ux500/clk.h12
-rw-r--r--drivers/clk/ux500/u8500_clk.c28
-rw-r--r--drivers/clk/versatile/Makefile3
-rw-r--r--drivers/clk/versatile/clk-icst.c66
-rw-r--r--drivers/clk/versatile/clk-icst.h14
-rw-r--r--drivers/clk/versatile/clk-impd1.c97
-rw-r--r--drivers/clk/versatile/clk-integrator.c55
-rw-r--r--drivers/clk/versatile/clk-realview.c65
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c146
-rw-r--r--drivers/clk/versatile/clk-vexpress.c142
-rw-r--r--drivers/cpufreq/Kconfig.arm7
-rw-r--r--drivers/cpufreq/Makefile5
-rw-r--r--drivers/cpufreq/cpufreq-cpu0.c2
-rw-r--r--drivers/cpufreq/cpufreq.c37
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c558
-rw-r--r--drivers/cpufreq/cpufreq_governor.c318
-rw-r--r--drivers/cpufreq/cpufreq_governor.h176
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c731
-rw-r--r--drivers/cpufreq/cpufreq_performance.c2
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c2
-rw-r--r--drivers/cpufreq/cpufreq_stats.c4
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c2
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c101
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c11
-rw-r--r--drivers/cpufreq/freq_table.c2
-rw-r--r--drivers/cpufreq/longhaul.c4
-rw-r--r--drivers/cpufreq/powernow-k8.c4
-rw-r--r--drivers/cpufreq/spear-cpufreq.c291
-rw-r--r--drivers/cpuidle/Kconfig9
-rw-r--r--drivers/cpuidle/cpuidle.c55
-rw-r--r--drivers/cpuidle/cpuidle.h13
-rw-r--r--drivers/cpuidle/driver.c209
-rw-r--r--drivers/cpuidle/governors/menu.c168
-rw-r--r--drivers/cpuidle/sysfs.c201
-rw-r--r--drivers/crypto/Kconfig2
-rw-r--r--drivers/crypto/ixp4xx_crypto.c12
-rw-r--r--drivers/devfreq/Kconfig8
-rw-r--r--drivers/devfreq/devfreq.c921
-rw-r--r--drivers/devfreq/exynos4_bus.c45
-rw-r--r--drivers/devfreq/governor.h17
-rw-r--r--drivers/devfreq/governor_performance.c38
-rw-r--r--drivers/devfreq/governor_powersave.c38
-rw-r--r--drivers/devfreq/governor_simpleondemand.c55
-rw-r--r--drivers/devfreq/governor_userspace.c45
-rw-r--r--drivers/dma/dw_dmac.c4
-rw-r--r--drivers/dma/edma.c4
-rw-r--r--drivers/dma/fsldma.c4
-rw-r--r--drivers/dma/intel_mid_dma.c4
-rw-r--r--drivers/dma/ioat/pci.c2
-rw-r--r--drivers/dma/iop-adma.c10
-rw-r--r--drivers/dma/mmp_pdma.c6
-rw-r--r--drivers/dma/mmp_tdma.c6
-rw-r--r--drivers/dma/mpc512x_dma.c4
-rw-r--r--drivers/dma/mv_xor.c8
-rw-r--r--drivers/dma/pch_dma.c4
-rw-r--r--drivers/dma/pl330.c2
-rw-r--r--drivers/dma/ppc4xx/adma.c4
-rw-r--r--drivers/dma/sa11x0-dma.c6
-rw-r--r--drivers/dma/sh/shdma.c6
-rw-r--r--drivers/dma/sirf-dma.c4
-rw-r--r--drivers/dma/tegra20-apb-dma.c4
-rw-r--r--drivers/dma/timb_dma.c2
-rw-r--r--drivers/edac/Kconfig8
-rw-r--r--drivers/edac/amd64_edac.c297
-rw-r--r--drivers/edac/amd64_edac.h61
-rw-r--r--drivers/edac/amd64_edac_inj.c128
-rw-r--r--drivers/edac/edac_mc.c65
-rw-r--r--drivers/edac/edac_mc_sysfs.c39
-rw-r--r--drivers/edac/edac_module.c27
-rw-r--r--drivers/edac/edac_pci.c3
-rw-r--r--drivers/edac/edac_pci_sysfs.c12
-rw-r--r--drivers/edac/edac_stub.c2
-rw-r--r--drivers/edac/highbank_mc_edac.c8
-rw-r--r--drivers/edac/i7300_edac.c8
-rw-r--r--drivers/edac/i7core_edac.c6
-rw-r--r--drivers/edac/i82975x_edac.c11
-rw-r--r--drivers/edac/mce_amd.c254
-rw-r--r--drivers/edac/mce_amd.h11
-rw-r--r--drivers/edac/mce_amd_inj.c4
-rw-r--r--drivers/extcon/extcon-adc-jack.c6
-rw-r--r--drivers/extcon/extcon-arizona.c6
-rw-r--r--drivers/extcon/extcon-gpio.c6
-rw-r--r--drivers/extcon/extcon-max77693.c6
-rw-r--r--drivers/extcon/extcon-max8997.c6
-rw-r--r--drivers/firewire/nosy.c4
-rw-r--r--drivers/firewire/ohci.c2
-rw-r--r--drivers/firewire/sbp2.c2
-rw-r--r--drivers/gpio/Kconfig38
-rw-r--r--drivers/gpio/Makefile5
-rw-r--r--drivers/gpio/gpio-74x164.c6
-rw-r--r--drivers/gpio/gpio-ab8500.c6
-rw-r--r--drivers/gpio/gpio-adnp.c10
-rw-r--r--drivers/gpio/gpio-adp5520.c6
-rw-r--r--drivers/gpio/gpio-adp5588.c6
-rw-r--r--drivers/gpio/gpio-arizona.c6
-rw-r--r--drivers/gpio/gpio-clps711x.c199
-rw-r--r--drivers/gpio/gpio-cs5535.c6
-rw-r--r--drivers/gpio/gpio-da9052.c8
-rw-r--r--drivers/gpio/gpio-da9055.c204
-rw-r--r--drivers/gpio/gpio-em.c54
-rw-r--r--drivers/gpio/gpio-ep93xx.c2
-rw-r--r--drivers/gpio/gpio-generic.c6
-rw-r--r--drivers/gpio/gpio-ich.c10
-rw-r--r--drivers/gpio/gpio-janz-ttl.c10
-rw-r--r--drivers/gpio/gpio-langwell.c8
-rw-r--r--drivers/gpio/gpio-lpc32xx.c4
-rw-r--r--drivers/gpio/gpio-max7300.c6
-rw-r--r--drivers/gpio/gpio-max7301.c6
-rw-r--r--drivers/gpio/gpio-max730x.c16
-rw-r--r--drivers/gpio/gpio-max732x.c8
-rw-r--r--drivers/gpio/gpio-mc33880.c6
-rw-r--r--drivers/gpio/gpio-mcp23s08.c12
-rw-r--r--drivers/gpio/gpio-ml-ioh.c8
-rw-r--r--drivers/gpio/gpio-mpc5200.c4
-rw-r--r--drivers/gpio/gpio-msic.c2
-rw-r--r--drivers/gpio/gpio-msm-v2.c6
-rw-r--r--drivers/gpio/gpio-mvebu.c36
-rw-r--r--drivers/gpio/gpio-mxc.c4
-rw-r--r--drivers/gpio/gpio-mxs.c2
-rw-r--r--drivers/gpio/gpio-omap.c8
-rw-r--r--drivers/gpio/gpio-pca953x.c61
-rw-r--r--drivers/gpio/gpio-pcf857x.c29
-rw-r--r--drivers/gpio/gpio-pch.c9
-rw-r--r--drivers/gpio/gpio-pl061.c66
-rw-r--r--drivers/gpio/gpio-pxa.c6
-rw-r--r--drivers/gpio/gpio-rc5t583.c6
-rw-r--r--drivers/gpio/gpio-rdc321x.c6
-rw-r--r--drivers/gpio/gpio-sch.c6
-rw-r--r--drivers/gpio/gpio-sodaville.c4
-rw-r--r--drivers/gpio/gpio-spear-spics.c217
-rw-r--r--drivers/gpio/gpio-sta2x11.c4
-rw-r--r--drivers/gpio/gpio-stmpe.c94
-rw-r--r--drivers/gpio/gpio-stp-xway.c2
-rw-r--r--drivers/gpio/gpio-sx150x.c6
-rw-r--r--drivers/gpio/gpio-tc3589x.c26
-rw-r--r--drivers/gpio/gpio-tegra.c47
-rw-r--r--drivers/gpio/gpio-timberdale.c4
-rw-r--r--drivers/gpio/gpio-tps6586x.c6
-rw-r--r--drivers/gpio/gpio-tps65910.c6
-rw-r--r--drivers/gpio/gpio-tps65912.c6
-rw-r--r--drivers/gpio/gpio-ts5500.c466
-rw-r--r--drivers/gpio/gpio-twl4030.c43
-rw-r--r--drivers/gpio/gpio-twl6040.c4
-rw-r--r--drivers/gpio/gpio-vr41xx.c6
-rw-r--r--drivers/gpio/gpio-vt8500.c4
-rw-r--r--drivers/gpio/gpio-vx855.c6
-rw-r--r--drivers/gpio/gpio-wm831x.c6
-rw-r--r--drivers/gpio/gpio-wm8350.c6
-rw-r--r--drivers/gpio/gpio-wm8994.c6
-rw-r--r--drivers/gpio/gpio-xilinx.c4
-rw-r--r--drivers/gpio/gpiolib-acpi.c54
-rw-r--r--drivers/gpio/gpiolib-of.c52
-rw-r--r--drivers/gpio/gpiolib.c200
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_encoder.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c6
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c11
-rw-r--r--drivers/gpu/drm/i915/intel_display.c2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c12
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c19
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/object.h14
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/clock.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c19
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c3
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c48
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_agp.c5
-rw-r--r--drivers/hv/Kconfig6
-rw-r--r--drivers/hv/Makefile1
-rw-r--r--drivers/hv/channel.c8
-rw-r--r--drivers/hv/channel_mgmt.c8
-rw-r--r--drivers/hv/hv_balloon.c1041
-rw-r--r--drivers/hwmon/Kconfig19
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/abituguru.c12
-rw-r--r--drivers/hwmon/abituguru3.c6
-rw-r--r--drivers/hwmon/ad7314.c6
-rw-r--r--drivers/hwmon/ad7414.c4
-rw-r--r--drivers/hwmon/adcxx.c6
-rw-r--r--drivers/hwmon/ads7828.c247
-rw-r--r--drivers/hwmon/ads7871.c6
-rw-r--r--drivers/hwmon/adt7411.c6
-rw-r--r--drivers/hwmon/coretemp.c68
-rw-r--r--drivers/hwmon/da9052-hwmon.c33
-rw-r--r--drivers/hwmon/da9055-hwmon.c336
-rw-r--r--drivers/hwmon/dme1737.c6
-rw-r--r--drivers/hwmon/f71805f.c8
-rw-r--r--drivers/hwmon/f71882fg.c8
-rw-r--r--drivers/hwmon/fam15h_power.c14
-rw-r--r--drivers/hwmon/gpio-fan.c8
-rw-r--r--drivers/hwmon/hih6130.c6
-rw-r--r--drivers/hwmon/i5k_amb.c18
-rw-r--r--drivers/hwmon/ina2xx.c13
-rw-r--r--drivers/hwmon/it87.c12
-rw-r--r--drivers/hwmon/jz4740-hwmon.c6
-rw-r--r--drivers/hwmon/k10temp.c8
-rw-r--r--drivers/hwmon/k8temp.c8
-rw-r--r--drivers/hwmon/lm70.c6
-rw-r--r--drivers/hwmon/lm78.c6
-rw-r--r--drivers/hwmon/max1111.c8
-rw-r--r--drivers/hwmon/max197.c6
-rw-r--r--drivers/hwmon/mc13783-adc.c4
-rw-r--r--drivers/hwmon/ntc_thermistor.c6
-rw-r--r--drivers/hwmon/pc87360.c8
-rw-r--r--drivers/hwmon/pc87427.c10
-rw-r--r--drivers/hwmon/s3c-hwmon.c6
-rw-r--r--drivers/hwmon/sch5627.c4
-rw-r--r--drivers/hwmon/sch5636.c2
-rw-r--r--drivers/hwmon/sht15.c6
-rw-r--r--drivers/hwmon/sht21.c6
-rw-r--r--drivers/hwmon/sis5595.c16
-rw-r--r--drivers/hwmon/smsc47b397.c6
-rw-r--r--drivers/hwmon/tmp102.c6
-rw-r--r--drivers/hwmon/twl4030-madc-hwmon.c4
-rw-r--r--drivers/hwmon/ultra45_env.c6
-rw-r--r--drivers/hwmon/via-cputemp.c6
-rw-r--r--drivers/hwmon/via686a.c14
-rw-r--r--drivers/hwmon/vt1211.c8
-rw-r--r--drivers/hwmon/vt8231.c12
-rw-r--r--drivers/hwmon/w83627ehf.c12
-rw-r--r--drivers/hwmon/w83627hf.c14
-rw-r--r--drivers/hwmon/w83781d.c6
-rw-r--r--drivers/hwmon/wm831x-hwmon.c6
-rw-r--r--drivers/hwmon/wm8350-hwmon.c6
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c6
-rw-r--r--drivers/hwspinlock/u8500_hsem.c6
-rw-r--r--drivers/i2c/busses/i2c-at91.c7
-rw-r--r--drivers/i2c/busses/i2c-mxs.c2
-rw-r--r--drivers/i2c/busses/i2c-ocores.c4
-rw-r--r--drivers/i2c/busses/i2c-omap.c36
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c1
-rw-r--r--drivers/i2c/i2c-core.c6
-rw-r--r--drivers/idle/intel_idle.c14
-rw-r--r--drivers/input/input-mt.c4
-rw-r--r--drivers/input/matrix-keymap.c3
-rw-r--r--drivers/input/mousedev.c4
-rw-r--r--drivers/input/touchscreen/ads7846.c6
-rw-r--r--drivers/iommu/intel-iommu.c4
-rw-r--r--drivers/iommu/tegra-smmu.c1
-rw-r--r--drivers/leds/leds-adp5520.c8
-rw-r--r--drivers/leds/leds-asic3.c6
-rw-r--r--drivers/leds/leds-atmel-pwm.c2
-rw-r--r--drivers/leds/leds-bd2802.c2
-rw-r--r--drivers/leds/leds-blinkm.c6
-rw-r--r--drivers/leds/leds-clevo-mail.c2
-rw-r--r--drivers/leds/leds-cobalt-qube.c6
-rw-r--r--drivers/leds/leds-cobalt-raq.c6
-rw-r--r--drivers/leds/leds-da903x.c6
-rw-r--r--drivers/leds/leds-da9052.c6
-rw-r--r--drivers/leds/leds-gpio.c12
-rw-r--r--drivers/leds/leds-lm3530.c6
-rw-r--r--drivers/leds/leds-lm3533.c8
-rw-r--r--drivers/leds/leds-lm355x.c8
-rw-r--r--drivers/leds/leds-lm3642.c8
-rw-r--r--drivers/leds/leds-lp3944.c6
-rw-r--r--drivers/leds/leds-lp5521.c8
-rw-r--r--drivers/leds/leds-lp5523.c4
-rw-r--r--drivers/leds/leds-lp8788.c6
-rw-r--r--drivers/leds/leds-lt3593.c8
-rw-r--r--drivers/leds/leds-max8997.c6
-rw-r--r--drivers/leds/leds-mc13783.c10
-rw-r--r--drivers/leds/leds-netxbig.c10
-rw-r--r--drivers/leds/leds-ns2.c8
-rw-r--r--drivers/leds/leds-ot200.c6
-rw-r--r--drivers/leds/leds-pca955x.c6
-rw-r--r--drivers/leds/leds-pca9633.c6
-rw-r--r--drivers/leds/leds-pwm.c4
-rw-r--r--drivers/leds/leds-rb532.c6
-rw-r--r--drivers/leds/leds-regulator.c6
-rw-r--r--drivers/leds/leds-renesas-tpu.c6
-rw-r--r--drivers/leds/leds-ss4200.c4
-rw-r--r--drivers/leds/leds-sunfire.c12
-rw-r--r--drivers/leds/leds-tca6507.c6
-rw-r--r--drivers/md/dm.c8
-rw-r--r--drivers/md/md.c27
-rw-r--r--drivers/md/raid1.c2
-rw-r--r--drivers/md/raid10.c133
-rw-r--r--drivers/md/raid5.c79
-rw-r--r--drivers/media/dvb-frontends/stv0900_core.c6
-rw-r--r--drivers/media/i2c/adv7604.c377
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c11
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.c6
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-m2m.c4
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-regs.h16
-rw-r--r--drivers/media/platform/omap3isp/ispccdc.c4
-rw-r--r--drivers/media/platform/omap3isp/ispstat.c4
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h4
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c2
-rw-r--r--drivers/media/platform/s5p-fimc/Kconfig1
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-capture.c14
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-lite.c10
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-m2m.c3
-rw-r--r--drivers/media/platform/s5p-fimc/fimc-mdevice.c41
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc.c7
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c2
-rw-r--r--drivers/media/platform/sh_vou.c3
-rw-r--r--drivers/media/platform/soc_camera/mx1_camera.c9
-rw-r--r--drivers/media/platform/soc_camera/mx2_camera.c13
-rw-r--r--drivers/media/platform/soc_camera/mx3_camera.c5
-rw-r--r--drivers/media/platform/soc_camera/omap1_camera.c4
-rw-r--r--drivers/media/platform/soc_camera/pxa_camera.c4
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c13
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c11
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c4
-rw-r--r--drivers/media/usb/dvb-usb-v2/rtl28xxu.c4
-rw-r--r--drivers/memstick/host/Kconfig10
-rw-r--r--drivers/memstick/host/Makefile1
-rw-r--r--drivers/memstick/host/rtsx_pci_ms.c641
-rw-r--r--drivers/mfd/88pm800.c12
-rw-r--r--drivers/mfd/88pm805.c10
-rw-r--r--drivers/mfd/88pm80x.c2
-rw-r--r--drivers/mfd/88pm860x-core.c104
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/ab3100-core.c13
-rw-r--r--drivers/mfd/ab8500-core.c40
-rw-r--r--drivers/mfd/ab8500-debugfs.c6
-rw-r--r--drivers/mfd/ab8500-gpadc.c6
-rw-r--r--drivers/mfd/ab8500-sysctrl.c6
-rw-r--r--drivers/mfd/adp5520.c6
-rw-r--r--drivers/mfd/arizona-core.c18
-rw-r--r--drivers/mfd/arizona-i2c.c6
-rw-r--r--drivers/mfd/arizona-irq.c1
-rw-r--r--drivers/mfd/arizona-spi.c6
-rw-r--r--drivers/mfd/asic3.c4
-rw-r--r--drivers/mfd/cs5535-mfd.c12
-rw-r--r--drivers/mfd/da903x.c10
-rw-r--r--drivers/mfd/da9052-core.c4
-rw-r--r--drivers/mfd/da9052-i2c.c6
-rw-r--r--drivers/mfd/da9052-spi.c6
-rw-r--r--drivers/mfd/da9055-core.c4
-rw-r--r--drivers/mfd/da9055-i2c.c6
-rw-r--r--drivers/mfd/davinci_voicecodec.c4
-rw-r--r--drivers/mfd/db8500-prcmu.c88
-rw-r--r--drivers/mfd/ezx-pcap.c8
-rw-r--r--drivers/mfd/htc-i2cpld.c12
-rw-r--r--drivers/mfd/intel_msic.c10
-rw-r--r--drivers/mfd/janz-cmodio.c10
-rw-r--r--drivers/mfd/jz4740-adc.c6
-rw-r--r--drivers/mfd/lm3533-core.c18
-rw-r--r--drivers/mfd/lp8788.c4
-rw-r--r--drivers/mfd/lpc_ich.c20
-rw-r--r--drivers/mfd/lpc_sch.c6
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max8907.c4
-rw-r--r--drivers/mfd/max8925-core.c58
-rw-r--r--drivers/mfd/max8925-i2c.c6
-rw-r--r--drivers/mfd/mc13xxx-i2c.c4
-rw-r--r--drivers/mfd/mc13xxx-spi.c4
-rw-r--r--drivers/mfd/omap-usb-host.c4
-rw-r--r--drivers/mfd/omap-usb-tll.c6
-rw-r--r--drivers/mfd/palmas.c6
-rw-r--r--drivers/mfd/pcf50633-adc.c6
-rw-r--r--drivers/mfd/pcf50633-core.c6
-rw-r--r--drivers/mfd/pm8921-core.c8
-rw-r--r--drivers/mfd/pm8xxx-irq.c4
-rw-r--r--drivers/mfd/rc5t583.c6
-rw-r--r--drivers/mfd/rdc321x-southbridge.c6
-rw-r--r--drivers/mfd/rtl8411.c251
-rw-r--r--drivers/mfd/rts5209.c223
-rw-r--r--drivers/mfd/rts5229.c205
-rw-r--r--drivers/mfd/rtsx_pcr.c1251
-rw-r--r--drivers/mfd/rtsx_pcr.h32
-rw-r--r--drivers/mfd/sm501.c16
-rw-r--r--drivers/mfd/sta2x11-mfd.c20
-rw-r--r--drivers/mfd/stmpe-i2c.c6
-rw-r--r--drivers/mfd/stmpe-spi.c6
-rw-r--r--drivers/mfd/stmpe.c2
-rw-r--r--drivers/mfd/syscon.c6
-rw-r--r--drivers/mfd/tc3589x.c8
-rw-r--r--drivers/mfd/tc6387xb.c6
-rw-r--r--drivers/mfd/tc6393xb.c12
-rw-r--r--drivers/mfd/ti-ssp.c6
-rw-r--r--drivers/mfd/timberdale.c64
-rw-r--r--drivers/mfd/tps6105x.c8
-rw-r--r--drivers/mfd/tps65090.c8
-rw-r--r--drivers/mfd/tps65217.c6
-rw-r--r--drivers/mfd/tps6586x.c10
-rw-r--r--drivers/mfd/tps65910.c10
-rw-r--r--drivers/mfd/tps65911-comparator.c6
-rw-r--r--drivers/mfd/tps65912-spi.c6
-rw-r--r--drivers/mfd/twl-core.c4
-rw-r--r--drivers/mfd/twl4030-audio.c6
-rw-r--r--drivers/mfd/twl4030-irq.c3
-rw-r--r--drivers/mfd/twl4030-madc.c4
-rw-r--r--drivers/mfd/twl4030-power.c20
-rw-r--r--drivers/mfd/vx855.c6
-rw-r--r--drivers/mfd/wl1273-core.c4
-rw-r--r--drivers/mfd/wm5102-tables.c519
-rw-r--r--drivers/mfd/wm831x-spi.c6
-rw-r--r--drivers/mfd/wm8994-core.c16
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c6
-rw-r--r--drivers/misc/ad525x_dpot-spi.c6
-rw-r--r--drivers/misc/ad525x_dpot.c4
-rw-r--r--drivers/misc/apds9802als.c6
-rw-r--r--drivers/misc/apds990x.c6
-rw-r--r--drivers/misc/atmel-ssc.c4
-rw-r--r--drivers/misc/bh1770glc.c6
-rw-r--r--drivers/misc/bh1780gli.c6
-rw-r--r--drivers/misc/bmp085-i2c.c4
-rw-r--r--drivers/misc/bmp085-spi.c4
-rw-r--r--drivers/misc/bmp085.c2
-rw-r--r--drivers/misc/cb710/core.c10
-rw-r--r--drivers/misc/cs5535-mfgpt.c6
-rw-r--r--drivers/misc/eeprom/at24.c4
-rw-r--r--drivers/misc/eeprom/at25.c4
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c6
-rw-r--r--drivers/misc/fsa9480.c6
-rw-r--r--drivers/misc/hpilo.c21
-rw-r--r--drivers/misc/ibmasm/module.c6
-rw-r--r--drivers/misc/ioc4.c10
-rw-r--r--drivers/misc/isl29003.c6
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c6
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_spi.c6
-rw-r--r--drivers/misc/mei/Makefile1
-rw-r--r--drivers/misc/mei/amthif.c722
-rw-r--r--drivers/misc/mei/hw.h36
-rw-r--r--drivers/misc/mei/init.c368
-rw-r--r--drivers/misc/mei/interface.c91
-rw-r--r--drivers/misc/mei/interrupt.c760
-rw-r--r--drivers/misc/mei/iorw.c455
-rw-r--r--drivers/misc/mei/main.c462
-rw-r--r--drivers/misc/mei/mei_dev.h155
-rw-r--r--drivers/misc/mei/wd.c15
-rw-r--r--drivers/misc/pch_phub.c6
-rw-r--r--drivers/misc/phantom.c10
-rw-r--r--drivers/misc/pti.c8
-rw-r--r--drivers/misc/spear13xx_pcie_gadget.c4
-rw-r--r--drivers/misc/ti-st/st_core.c1
-rw-r--r--drivers/misc/ti-st/st_kim.c30
-rw-r--r--drivers/misc/ti_dac7512.c6
-rw-r--r--drivers/misc/tsl2550.c6
-rw-r--r--drivers/mmc/card/block.c81
-rw-r--r--drivers/mmc/card/queue.c17
-rw-r--r--drivers/mmc/core/bus.c3
-rw-r--r--drivers/mmc/core/core.c32
-rw-r--r--drivers/mmc/core/debugfs.c16
-rw-r--r--drivers/mmc/core/mmc.c19
-rw-r--r--drivers/mmc/core/mmc_ops.c11
-rw-r--r--drivers/mmc/core/sdio_bus.c17
-rw-r--r--drivers/mmc/core/sdio_io.c10
-rw-r--r--drivers/mmc/core/sdio_ops.c32
-rw-r--r--drivers/mmc/core/slot-gpio.c8
-rw-r--r--drivers/mmc/host/Kconfig52
-rw-r--r--drivers/mmc/host/Makefile5
-rw-r--r--drivers/mmc/host/at91_mci.c1219
-rw-r--r--drivers/mmc/host/at91_mci.h115
-rw-r--r--drivers/mmc/host/atmel-mci.c2
-rw-r--r--drivers/mmc/host/au1xmmc.c4
-rw-r--r--drivers/mmc/host/bfin_sdh.c6
-rw-r--r--drivers/mmc/host/cb710-mmc.c6
-rw-r--r--drivers/mmc/host/dw_mmc-pci.c6
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c20
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.h2
-rw-r--r--drivers/mmc/host/dw_mmc.c86
-rw-r--r--drivers/mmc/host/jz4740_mmc.c12
-rw-r--r--drivers/mmc/host/mmc_spi.c6
-rw-r--r--drivers/mmc/host/mmci.c10
-rw-r--r--drivers/mmc/host/mxcmmc.c2
-rw-r--r--drivers/mmc/host/mxs-mmc.c31
-rw-r--r--drivers/mmc/host/omap.c8
-rw-r--r--drivers/mmc/host/omap_hsmmc.c183
-rw-r--r--drivers/mmc/host/pxamci.c4
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c1348
-rw-r--r--drivers/mmc/host/s3cmci.c6
-rw-r--r--drivers/mmc/host/sdhci-acpi.c312
-rw-r--r--drivers/mmc/host/sdhci-cns3xxx.c6
-rw-r--r--drivers/mmc/host/sdhci-dove.c116
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c64
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c60
-rw-r--r--drivers/mmc/host/sdhci-of-hlwd.c6
-rw-r--r--drivers/mmc/host/sdhci-pci.c15
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c9
-rw-r--r--drivers/mmc/host/sdhci-pxav2.c6
-rw-r--r--drivers/mmc/host/sdhci-pxav3.c19
-rw-r--r--drivers/mmc/host/sdhci-s3c.c75
-rw-r--r--drivers/mmc/host/sdhci-spear.c21
-rw-r--r--drivers/mmc/host/sdhci-tegra.c10
-rw-r--r--drivers/mmc/host/sdhci.c79
-rw-r--r--drivers/mmc/host/sdhci.h5
-rw-r--r--drivers/mmc/host/sh_mmcif.c18
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c12
-rw-r--r--drivers/mmc/host/tmio_mmc.c6
-rw-r--r--drivers/mmc/host/tmio_mmc_pio.c2
-rw-r--r--drivers/mmc/host/via-sdmmc.c6
-rw-r--r--drivers/mmc/host/vub300.c1
-rw-r--r--drivers/mmc/host/wbsd.c28
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c1029
-rw-r--r--drivers/mtd/devices/slram.c2
-rw-r--r--drivers/mtd/mtdcore.c6
-rw-r--r--drivers/mtd/nand/atmel_nand.c9
-rw-r--r--drivers/mtd/nand/nand_base.c10
-rw-r--r--drivers/mtd/nand/sh_flctl.c4
-rw-r--r--drivers/mtd/ofpart.c2
-rw-r--r--drivers/mtd/onenand/onenand_base.c2
-rw-r--r--drivers/mtd/ubi/wl.c26
-rw-r--r--drivers/net/bonding/bond_main.c100
-rw-r--r--drivers/net/bonding/bond_sysfs.c36
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb.c8
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_pro.c8
-rw-r--r--drivers/net/ethernet/8390/ne.c1
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c2
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c33
-rw-r--r--drivers/net/ethernet/sis/sis900.c2
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_axienet_main.c2
-rw-r--r--drivers/net/ethernet/xscale/ixp4xx_eth.c8
-rw-r--r--drivers/net/irda/sir_dev.c2
-rw-r--r--drivers/net/phy/mdio-gpio.c11
-rw-r--r--drivers/net/team/team.c4
-rw-r--r--drivers/net/team/team_mode_broadcast.c6
-rw-r--r--drivers/net/usb/qmi_wwan.c1
-rw-r--r--drivers/net/wan/ixp4xx_hss.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c14
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c12
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c8
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c11
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c11
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c1
-rw-r--r--drivers/net/xen-netfront.c98
-rw-r--r--drivers/nfc/pn533.c25
-rw-r--r--drivers/of/base.c128
-rw-r--r--drivers/of/fdt.c18
-rw-r--r--drivers/of/of_i2c.c2
-rw-r--r--drivers/of/of_mdio.c2
-rw-r--r--drivers/of/pdt.c12
-rw-r--r--drivers/parport/Kconfig16
-rw-r--r--drivers/pci/Makefile7
-rw-r--r--drivers/pci/hotplug.c37
-rw-r--r--drivers/pci/hotplug/cpcihp_zt5550.c4
-rw-r--r--drivers/pci/ioapic.c6
-rw-r--r--drivers/pci/pci-acpi.c79
-rw-r--r--drivers/pci/pci-driver.c42
-rw-r--r--drivers/pci/pci-sysfs.c7
-rw-r--r--drivers/pci/pci.c4
-rw-r--r--drivers/pci/pci.h5
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c4
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c20
-rw-r--r--drivers/pci/quirks.c132
-rw-r--r--drivers/pci/xen-pcifront.c10
-rw-r--r--drivers/pcmcia/bcm63xx_pcmcia.c12
-rw-r--r--drivers/pcmcia/bfin_cf_pcmcia.c6
-rw-r--r--drivers/pcmcia/db1xxx_ss.c6
-rw-r--r--drivers/pcmcia/ds.c13
-rw-r--r--drivers/pcmcia/electra_cf.c4
-rw-r--r--drivers/pcmcia/i82092.c6
-rw-r--r--drivers/pcmcia/pd6729.c8
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c2
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c6
-rw-r--r--drivers/pcmcia/sa1100_assabet.c2
-rw-r--r--drivers/pcmcia/sa1100_cerf.c2
-rw-r--r--drivers/pcmcia/sa1100_generic.c4
-rw-r--r--drivers/pcmcia/sa1100_h3600.c2
-rw-r--r--drivers/pcmcia/sa1100_shannon.c2
-rw-r--r--drivers/pcmcia/sa1100_simpad.c2
-rw-r--r--drivers/pcmcia/sa1111_generic.c4
-rw-r--r--drivers/pcmcia/sa1111_jornada720.c2
-rw-r--r--drivers/pcmcia/vrc4171_card.c8
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c8
-rw-r--r--drivers/pcmcia/xxs1500_ss.c6
-rw-r--r--drivers/pcmcia/yenta_socket.c6
-rw-r--r--drivers/pinctrl/Kconfig52
-rw-r--r--drivers/pinctrl/Makefile7
-rw-r--r--drivers/pinctrl/core.c58
-rw-r--r--drivers/pinctrl/core.h2
-rw-r--r--drivers/pinctrl/devicetree.c11
-rw-r--r--drivers/pinctrl/mvebu/Kconfig24
-rw-r--r--drivers/pinctrl/mvebu/Makefile5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-370.c (renamed from drivers/pinctrl/pinctrl-armada-370.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-xp.c (renamed from drivers/pinctrl/pinctrl-armada-xp.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-dove.c (renamed from drivers/pinctrl/pinctrl-dove.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-kirkwood.c (renamed from drivers/pinctrl/pinctrl-kirkwood.c)0
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c (renamed from drivers/pinctrl/pinctrl-mvebu.c)1
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.h (renamed from drivers/pinctrl/pinctrl-mvebu.h)0
-rw-r--r--drivers/pinctrl/pinconf-generic.c1
-rw-r--r--drivers/pinctrl/pinctrl-at91.c1634
-rw-r--r--drivers/pinctrl/pinctrl-bcm2835.c10
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c175
-rw-r--r--drivers/pinctrl/pinctrl-exynos.c1
-rw-r--r--drivers/pinctrl/pinctrl-falcon.c2
-rw-r--r--drivers/pinctrl/pinctrl-imx.c6
-rw-r--r--drivers/pinctrl/pinctrl-imx23.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx28.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx35.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx51.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx53.c4
-rw-r--r--drivers/pinctrl/pinctrl-imx6q.c4
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.c23
-rw-r--r--drivers/pinctrl/pinctrl-mmp2.c4
-rw-r--r--drivers/pinctrl/pinctrl-mxs.c4
-rw-r--r--drivers/pinctrl/pinctrl-nomadik-db8500.c125
-rw-r--r--drivers/pinctrl/pinctrl-nomadik-db8540.c16
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.c152
-rw-r--r--drivers/pinctrl/pinctrl-nomadik.h2
-rw-r--r--drivers/pinctrl/pinctrl-pxa168.c4
-rw-r--r--drivers/pinctrl/pinctrl-pxa3xx.c12
-rw-r--r--drivers/pinctrl/pinctrl-pxa3xx.h2
-rw-r--r--drivers/pinctrl/pinctrl-pxa910.c4
-rw-r--r--drivers/pinctrl/pinctrl-single.c96
-rw-r--r--drivers/pinctrl/pinctrl-sirf.c54
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c26
-rw-r--r--drivers/pinctrl/pinctrl-tegra20.c4
-rw-r--r--drivers/pinctrl/pinctrl-tegra30.c4
-rw-r--r--drivers/pinctrl/pinctrl-u300.c101
-rw-r--r--drivers/pinctrl/pinctrl-xway.c2
-rw-r--r--drivers/pinctrl/pinmux.c85
-rw-r--r--drivers/pinctrl/spear/Kconfig11
-rw-r--r--drivers/pinctrl/spear/Makefile1
-rw-r--r--drivers/pinctrl/spear/pinctrl-plgpio.c758
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c133
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.h62
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear1310.c270
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear1340.c33
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear300.c8
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear310.c8
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear320.c8
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear3xx.c37
-rw-r--r--drivers/pnp/base.h2
-rw-r--r--drivers/pnp/pnpacpi/core.c9
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c296
-rw-r--r--drivers/pnp/pnpbios/core.c20
-rw-r--r--drivers/pnp/resource.c16
-rw-r--r--drivers/power/88pm860x_battery.c6
-rw-r--r--drivers/power/88pm860x_charger.c6
-rw-r--r--drivers/power/ab8500_btemp.c6
-rw-r--r--drivers/power/ab8500_charger.c6
-rw-r--r--drivers/power/ab8500_fg.c6
-rw-r--r--drivers/power/abx500_chargalg.c6
-rw-r--r--drivers/power/avs/smartreflex.c8
-rw-r--r--drivers/power/bq27x00_battery.c6
-rw-r--r--drivers/power/charger-manager.c4
-rw-r--r--drivers/power/collie_battery.c6
-rw-r--r--drivers/power/da9052-battery.c6
-rw-r--r--drivers/power/ds2780_battery.c6
-rw-r--r--drivers/power/ds2781_battery.c6
-rw-r--r--drivers/power/generic-adc-battery.c6
-rw-r--r--drivers/power/gpio-charger.c6
-rw-r--r--drivers/power/intel_mid_battery.c8
-rw-r--r--drivers/power/isp1704_charger.c6
-rw-r--r--drivers/power/jz4740-battery.c6
-rw-r--r--drivers/power/lp8727_charger.c4
-rw-r--r--drivers/power/lp8788-charger.c6
-rw-r--r--drivers/power/max17040_battery.c6
-rw-r--r--drivers/power/max17042_battery.c6
-rw-r--r--drivers/power/max8903_charger.c6
-rw-r--r--drivers/power/max8925_power.c10
-rw-r--r--drivers/power/max8997_charger.c6
-rw-r--r--drivers/power/max8998_charger.c6
-rw-r--r--drivers/power/olpc_battery.c6
-rw-r--r--drivers/power/pcf50633-charger.c6
-rw-r--r--drivers/power/s3c_adc_battery.c2
-rw-r--r--drivers/power/sbs-battery.c6
-rw-r--r--drivers/power/smb347-charger.c2
-rw-r--r--drivers/power/tosa_battery.c6
-rw-r--r--drivers/power/wm831x_backup.c6
-rw-r--r--drivers/power/wm831x_power.c6
-rw-r--r--drivers/power/wm8350_power.c6
-rw-r--r--drivers/power/wm97xx_battery.c6
-rw-r--r--drivers/power/z2_battery.c6
-rw-r--r--drivers/ptp/ptp_pch.c4
-rw-r--r--drivers/pwm/pwm-ab8500.c6
-rw-r--r--drivers/pwm/pwm-bfin.c4
-rw-r--r--drivers/pwm/pwm-imx.c6
-rw-r--r--drivers/pwm/pwm-jz4740.c6
-rw-r--r--drivers/pwm/pwm-lpc32xx.c4
-rw-r--r--drivers/pwm/pwm-mxs.c4
-rw-r--r--drivers/pwm/pwm-puv3.c6
-rw-r--r--drivers/pwm/pwm-pxa.c6
-rw-r--r--drivers/pwm/pwm-samsung.c4
-rw-r--r--drivers/pwm/pwm-tegra.c4
-rw-r--r--drivers/pwm/pwm-tiecap.c6
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c6
-rw-r--r--drivers/pwm/pwm-twl6030.c2
-rw-r--r--drivers/rapidio/devices/tsi721.c4
-rw-r--r--drivers/rapidio/devices/tsi721.h2
-rw-r--r--drivers/rapidio/devices/tsi721_dma.c2
-rw-r--r--drivers/rapidio/rio-scan.c14
-rw-r--r--drivers/rapidio/rio.c6
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c18
-rw-r--r--drivers/rtc/rtc-tps65910.c6
-rw-r--r--drivers/scsi/isci/request.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c14
-rw-r--r--drivers/scsi/scsi.c45
-rw-r--r--drivers/scsi/scsi_lib.c22
-rw-r--r--drivers/scsi/sd.c202
-rw-r--r--drivers/scsi/sd.h7
-rw-r--r--drivers/spi/spi.c105
-rw-r--r--drivers/target/target_core_transport.c6
-rw-r--r--drivers/tty/serial/atmel_serial.c8
-rw-r--r--drivers/tty/vt/vt.c8
-rw-r--r--drivers/uio/Kconfig16
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio_aec.c2
-rw-r--r--drivers/uio/uio_cif.c4
-rw-r--r--drivers/uio/uio_dmem_genirq.c359
-rw-r--r--drivers/uio/uio_netx.c2
-rw-r--r--drivers/uio/uio_pci_generic.c2
-rw-r--r--drivers/uio/uio_pdrv.c1
-rw-r--r--drivers/uio/uio_pdrv_genirq.c3
-rw-r--r--drivers/uio/uio_pruss.c6
-rw-r--r--drivers/uio/uio_sercos3.c4
-rw-r--r--drivers/usb/storage/scsiglue.c6
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--drivers/video/backlight/adp5520_bl.c6
-rw-r--r--drivers/video/backlight/adp8860_bl.c14
-rw-r--r--drivers/video/backlight/adp8870_bl.c14
-rw-r--r--drivers/video/backlight/ams369fg06.c6
-rw-r--r--drivers/video/backlight/apple_bl.c4
-rw-r--r--drivers/video/backlight/corgi_lcd.c6
-rw-r--r--drivers/video/backlight/ep93xx_bl.c2
-rw-r--r--drivers/video/backlight/hp680_bl.c2
-rw-r--r--drivers/video/backlight/ili9320.c4
-rw-r--r--drivers/video/backlight/l4f00242t03.c6
-rw-r--r--drivers/video/backlight/ld9040.c4
-rw-r--r--drivers/video/backlight/lm3533_bl.c8
-rw-r--r--drivers/video/backlight/lm3630_bl.c8
-rw-r--r--drivers/video/backlight/lm3639_bl.c8
-rw-r--r--drivers/video/backlight/lms283gf05.c6
-rw-r--r--drivers/video/backlight/lp855x_bl.c4
-rw-r--r--drivers/video/backlight/ltv350qv.c6
-rw-r--r--drivers/video/backlight/max8925_bl.c6
-rw-r--r--drivers/video/backlight/pcf50633-backlight.c6
-rw-r--r--drivers/video/backlight/platform_lcd.c6
-rw-r--r--drivers/video/backlight/s6e63m0.c6
-rw-r--r--drivers/video/backlight/tdo24m.c6
-rw-r--r--drivers/video/backlight/tosa_bl.c6
-rw-r--r--drivers/video/backlight/tosa_lcd.c6
-rw-r--r--drivers/video/backlight/vgg2432a4.c6
-rw-r--r--drivers/video/omap2/dss/dsi.c13
-rw-r--r--drivers/video/omap2/dss/dss.c18
-rw-r--r--drivers/video/omap2/dss/hdmi.c4
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c2
-rw-r--r--drivers/w1/masters/Kconfig2
-rw-r--r--drivers/w1/masters/ds2482.c13
-rw-r--r--drivers/w1/masters/matrox_w1.c10
-rw-r--r--drivers/w1/masters/mxc_w1.c28
-rw-r--r--drivers/w1/masters/omap_hdq.c10
-rw-r--r--drivers/w1/masters/w1-gpio.c65
-rw-r--r--drivers/w1/w1.c7
-rw-r--r--drivers/watchdog/acquirewdt.c6
-rw-r--r--drivers/watchdog/advantechwdt.c6
-rw-r--r--drivers/watchdog/ar7_wdt.c6
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c6
-rw-r--r--drivers/watchdog/ath79_wdt.c6
-rw-r--r--drivers/watchdog/bcm63xx_wdt.c6
-rw-r--r--drivers/watchdog/bfin_wdt.c6
-rw-r--r--drivers/watchdog/cpu5wdt.c8
-rw-r--r--drivers/watchdog/cpwd.c6
-rw-r--r--drivers/watchdog/da9052_wdt.c6
-rw-r--r--drivers/watchdog/davinci_wdt.c6
-rw-r--r--drivers/watchdog/dw_wdt.c6
-rw-r--r--drivers/watchdog/ep93xx_wdt.c6
-rw-r--r--drivers/watchdog/gef_wdt.c4
-rw-r--r--drivers/watchdog/geodewdt.c6
-rw-r--r--drivers/watchdog/hpwdt.c30
-rw-r--r--drivers/watchdog/i6300esb.c10
-rw-r--r--drivers/watchdog/iTCO_wdt.c8
-rw-r--r--drivers/watchdog/ib700wdt.c6
-rw-r--r--drivers/watchdog/ie6xx_wdt.c10
-rw-r--r--drivers/watchdog/jz4740_wdt.c6
-rw-r--r--drivers/watchdog/ks8695_wdt.c6
-rw-r--r--drivers/watchdog/lantiq_wdt.c6
-rw-r--r--drivers/watchdog/max63xx_wdt.c6
-rw-r--r--drivers/watchdog/mixcomwd.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c6
-rw-r--r--drivers/watchdog/mpcore_wdt.c6
-rw-r--r--drivers/watchdog/mtx-1_wdt.c6
-rw-r--r--drivers/watchdog/mv64x60_wdt.c6
-rw-r--r--drivers/watchdog/nuc900_wdt.c6
-rw-r--r--drivers/watchdog/nv_tco.c10
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c8
-rw-r--r--drivers/watchdog/omap_wdt.c6
-rw-r--r--drivers/watchdog/orion_wdt.c8
-rw-r--r--drivers/watchdog/pcwd.c8
-rw-r--r--drivers/watchdog/pcwd_pci.c6
-rw-r--r--drivers/watchdog/pnx4008_wdt.c6
-rw-r--r--drivers/watchdog/rc32434_wdt.c6
-rw-r--r--drivers/watchdog/rdc321x_wdt.c6
-rw-r--r--drivers/watchdog/riowd.c6
-rw-r--r--drivers/watchdog/s3c2410_wdt.c6
-rw-r--r--drivers/watchdog/sch311x_wdt.c6
-rw-r--r--drivers/watchdog/shwdt.c6
-rw-r--r--drivers/watchdog/sp5100_tco.c10
-rw-r--r--drivers/watchdog/sp805_wdt.c6
-rw-r--r--drivers/watchdog/stmp3xxx_wdt.c6
-rw-r--r--drivers/watchdog/ts72xx_wdt.c6
-rw-r--r--drivers/watchdog/twl4030_wdt.c6
-rw-r--r--drivers/watchdog/via_wdt.c6
-rw-r--r--drivers/watchdog/wdt_pci.c6
-rw-r--r--drivers/watchdog/wm831x_wdt.c6
-rw-r--r--drivers/watchdog/wm8350_wdt.c6
-rw-r--r--drivers/watchdog/xen_wdt.c6
-rw-r--r--drivers/xen/privcmd.c18
-rw-r--r--drivers/xen/xen-selfballoon.c2
-rw-r--r--fs/block_dev.c166
-rw-r--r--fs/buffer.c145
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/readdir.c5
-rw-r--r--fs/cifs/smb1ops.c3
-rw-r--r--fs/debugfs/inode.c1
-rw-r--r--fs/direct-io.c8
-rw-r--r--fs/ext3/balloc.c5
-rw-r--r--fs/file.c15
-rw-r--r--fs/fs-writeback.c2
-rw-r--r--fs/inode.c16
-rw-r--r--fs/internal.h1
-rw-r--r--fs/jbd/transaction.c2
-rw-r--r--fs/jffs2/file.c39
-rw-r--r--fs/namei.c5
-rw-r--r--fs/nfs/dir.c7
-rw-r--r--fs/notify/fanotify/fanotify_user.c3
-rw-r--r--fs/proc/base.c5
-rw-r--r--fs/reiserfs/inode.c10
-rw-r--r--fs/reiserfs/stree.c4
-rw-r--r--fs/reiserfs/super.c60
-rw-r--r--fs/sysfs/file.c4
-rw-r--r--fs/xfs/xfs_aops.c54
-rw-r--r--fs/xfs/xfs_attr_leaf.c20
-rw-r--r--fs/xfs/xfs_buf.c14
-rw-r--r--include/acpi/acconfig.h1
-rw-r--r--include/acpi/acexcep.h2
-rw-r--r--include/acpi/acnames.h1
-rw-r--r--include/acpi/acpi_bus.h78
-rw-r--r--include/acpi/acpiosxf.h3
-rw-r--r--include/acpi/acpixf.h18
-rw-r--r--include/acpi/actbl3.h22
-rw-r--r--include/acpi/actypes.h42
-rw-r--r--include/asm-generic/gpio.h52
-rw-r--r--include/drm/drm_pciids.h1
-rw-r--r--include/linux/acpi.h135
-rw-r--r--include/linux/acpi_gpio.h19
-rw-r--r--include/linux/bug.h1
-rw-r--r--include/linux/clk-provider.h24
-rw-r--r--include/linux/cpufreq.h5
-rw-r--r--include/linux/cpuidle.h15
-rw-r--r--include/linux/devfreq.h136
-rw-r--r--include/linux/device.h18
-rw-r--r--include/linux/dma-contiguous.h4
-rw-r--r--include/linux/edac.h3
-rw-r--r--include/linux/freezer.h1
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/gfp.h5
-rw-r--r--include/linux/gpio.h21
-rw-r--r--include/linux/hw_breakpoint.h31
-rw-r--r--include/linux/i2c-omap.h1
-rw-r--r--include/linux/i2c.h9
-rw-r--r--include/linux/i2c/pcf857x.h3
-rw-r--r--include/linux/init.h18
-rw-r--r--include/linux/kernel.h7
-rw-r--r--include/linux/kobject.h18
-rw-r--r--include/linux/mempolicy.h16
-rw-r--r--include/linux/mfd/88pm80x.h2
-rw-r--r--include/linux/mfd/abx500/ab8500.h4
-rw-r--r--include/linux/mfd/db8500-prcmu.h4
-rw-r--r--include/linux/mfd/dbx500-prcmu.h10
-rw-r--r--include/linux/mfd/pm8xxx/irq.h8
-rw-r--r--include/linux/mfd/rtsx_common.h48
-rw-r--r--include/linux/mfd/rtsx_pci.h794
-rw-r--r--include/linux/mman.h2
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/core.h2
-rw-r--r--include/linux/mmc/dw_mmc.h5
-rw-r--r--include/linux/mmc/host.h17
-rw-r--r--include/linux/mmc/mmc.h2
-rw-r--r--include/linux/mmc/mxs-mmc.h19
-rw-r--r--include/linux/mmc/sdhci.h6
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--include/linux/of.h57
-rw-r--r--include/linux/of_address.h2
-rw-r--r--include/linux/pci.h8
-rw-r--r--include/linux/percpu-rwsem.h4
-rw-r--r--include/linux/pinctrl/pinconf-generic.h5
-rw-r--r--include/linux/pinctrl/pinctrl.h19
-rw-r--r--include/linux/platform_data/ads7828.h29
-rw-r--r--include/linux/platform_data/clk-integrator.h2
-rw-r--r--include/linux/platform_data/gpio-ts5500.h27
-rw-r--r--include/linux/platform_data/pinctrl-coh901.h4
-rw-r--r--include/linux/platform_data/pinctrl-nomadik.h (renamed from arch/arm/plat-nomadik/include/plat/pincfg.h)111
-rw-r--r--include/linux/platform_data/pxa_sdhci.h6
-rw-r--r--include/linux/platform_data/uio_dmem_genirq.h26
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/pm.h3
-rw-r--r--include/linux/pm_qos.h77
-rw-r--r--include/linux/spi/ads7846.h5
-rw-r--r--include/linux/tick.h6
-rw-r--r--include/media/adv7604.h21
-rw-r--r--include/net/tcp.h1
-rw-r--r--include/net/xfrm.h2
-rw-r--r--include/scsi/scsi_device.h4
-rw-r--r--include/trace/events/gfpflags.h1
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/hw_breakpoint.h30
-rw-r--r--kernel/cpu.c8
-rw-r--r--kernel/events/hw_breakpoint.c12
-rw-r--r--kernel/futex.c18
-rw-r--r--kernel/irq/irqdomain.c4
-rw-r--r--kernel/ksysfs.c5
-rw-r--r--kernel/modsign_pubkey.c4
-rw-r--r--kernel/module_signing.c14
-rw-r--r--kernel/power/main.c2
-rw-r--r--kernel/power/qos.c65
-rw-r--r--kernel/power/swap.c2
-rw-r--r--kernel/sched/auto_group.c4
-rw-r--r--kernel/sched/auto_group.h5
-rw-r--r--kernel/sysctl.c4
-rw-r--r--kernel/time/tick-sched.c4
-rw-r--r--kernel/watchdog.c7
-rw-r--r--kernel/workqueue.c22
-rw-r--r--lib/Makefile5
-rw-r--r--lib/asn1_decoder.c2
-rw-r--r--lib/mpi/longlong.h19
-rw-r--r--mm/compaction.c10
-rw-r--r--mm/dmapool.c31
-rw-r--r--mm/memory-failure.c8
-rw-r--r--mm/mempolicy.c22
-rw-r--r--mm/mmap.c14
-rw-r--r--mm/nommu.c15
-rw-r--r--mm/page_alloc.c11
-rw-r--r--mm/shmem.c26
-rw-r--r--mm/sparse.c10
-rw-r--r--mm/vmscan.c83
-rw-r--r--net/can/bcm.c3
-rw-r--r--net/core/dev.c2
-rw-r--r--net/core/net-sysfs.c20
-rw-r--r--net/core/skbuff.c6
-rw-r--r--net/ipv4/icmp.c3
-rw-r--r--net/ipv4/inet_diag.c154
-rw-r--r--net/ipv4/ip_fragment.c19
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/route.c9
-rw-r--r--net/ipv4/tcp.c15
-rw-r--r--net/ipv4/tcp_input.c6
-rw-r--r--net/ipv4/tcp_output.c15
-rw-r--r--net/ipv4/xfrm4_policy.c13
-rw-r--r--net/ipv6/inet6_connection_sock.c3
-rw-r--r--net/irda/irttp.c1
-rw-r--r--net/mac80211/ibss.c8
-rw-r--r--net/mac80211/offchannel.c2
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c4
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c7
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c7
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c7
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c2
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c3
-rw-r--r--net/nfc/llcp/llcp.c2
-rw-r--r--net/openvswitch/flow.c14
-rw-r--r--net/openvswitch/vport-netdev.c2
-rw-r--r--net/sctp/chunk.c20
-rw-r--r--net/sctp/socket.c4
-rw-r--r--net/sctp/transport.c2
-rw-r--r--scripts/Makefile.lib3
-rw-r--r--scripts/dtc/Makefile2
-rw-r--r--scripts/headers_install.pl3
-rw-r--r--scripts/mod/modpost.c24
-rwxr-xr-xscripts/sign-file6
-rw-r--r--security/selinux/netnode.c3
-rw-r--r--sound/pci/hda/hda_codec.c13
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_intel.c39
-rw-r--r--sound/pci/hda/patch_cirrus.c1
-rw-r--r--sound/pci/hda/patch_realtek.c1
-rw-r--r--sound/soc/codecs/arizona.c4
-rw-r--r--sound/soc/codecs/cs4271.c11
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c3
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c74
-rw-r--r--sound/soc/samsung/bells.c4
-rw-r--r--sound/usb/midi.c8
-rw-r--r--sound/usb/pcm.c2
-rw-r--r--tools/Makefile24
-rw-r--r--tools/hv/hv_kvp_daemon.c40
-rw-r--r--tools/perf/Makefile29
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h2
-rw-r--r--tools/perf/builtin-kvm.c121
-rw-r--r--tools/perf/builtin-test.c2
-rw-r--r--tools/perf/perf.h16
-rw-r--r--tools/perf/util/evsel.c4
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/parse-events-test.c2
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/pmu.h2
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/strbuf.c8
-rw-r--r--tools/power/cpupower/.gitignore7
-rw-r--r--tools/power/cpupower/Makefile3
-rw-r--r--tools/power/cpupower/debug/i386/Makefile5
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.115
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c2
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h18
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c19
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c53
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c21
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h17
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c10
-rw-r--r--tools/scripts/Makefile.include23
1480 files changed, 36052 insertions, 13839 deletions
diff --git a/CREDITS b/CREDITS
index d8fe12a9421f..2346b09ca8bb 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1823,6 +1823,11 @@ S: Kattreinstr 38
S: D-64295
S: Germany
+N: Avi Kivity
+E: avi.kivity@gmail.com
+D: Kernel-based Virtual Machine (KVM)
+S: Ra'annana, Israel
+
N: Andi Kleen
E: andi@firstfloor.org
U: http://www.halobates.de
diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
index 23d78b5aab11..0ba6ea2f89d9 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -11,7 +11,7 @@ What: /sys/class/devfreq/.../governor
Date: September 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
- The /sys/class/devfreq/.../governor shows the name of the
+ The /sys/class/devfreq/.../governor show or set the name of the
governor used by the corresponding devfreq object.
What: /sys/class/devfreq/.../cur_freq
@@ -19,15 +19,16 @@ Date: September 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
The /sys/class/devfreq/.../cur_freq shows the current
- frequency of the corresponding devfreq object.
+ frequency of the corresponding devfreq object. Same as
+ target_freq when get_cur_freq() is not implemented by
+ devfreq driver.
-What: /sys/class/devfreq/.../central_polling
-Date: September 2011
-Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+What: /sys/class/devfreq/.../target_freq
+Date: September 2012
+Contact: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Description:
- The /sys/class/devfreq/.../central_polling shows whether
- the devfreq ojbect is using devfreq-provided central
- polling mechanism or not.
+ The /sys/class/devfreq/.../target_freq shows the next governor
+ predicted target frequency of the corresponding devfreq object.
What: /sys/class/devfreq/.../polling_interval
Date: September 2011
@@ -43,6 +44,17 @@ Description:
(/sys/class/devfreq/.../central_polling is 0), this value
may be useless.
+What: /sys/class/devfreq/.../trans_stat
+Date: October 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Descrtiption:
+ This ABI shows the statistics of devfreq behavior on a
+ specific device. It shows the time spent in each state and
+ the number of transitions between states.
+ In order to activate this ABI, the devfreq target device
+ driver should provide the list of available frequencies
+ with its profile.
+
What: /sys/class/devfreq/.../userspace/set_freq
Date: September 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -50,3 +62,19 @@ Description:
The /sys/class/devfreq/.../userspace/set_freq shows and
sets the requested frequency for the devfreq object if
userspace governor is in effect.
+
+What: /sys/class/devfreq/.../available_frequencies
+Date: October 2012
+Contact: Nishanth Menon <nm@ti.com>
+Description:
+ The /sys/class/devfreq/.../available_frequencies shows
+ the available frequencies of the corresponding devfreq object.
+ This is a snapshot of available frequencies and not limited
+ by the min/max frequency restrictions.
+
+What: /sys/class/devfreq/.../available_governors
+Date: October 2012
+Contact: Nishanth Menon <nm@ti.com>
+Description:
+ The /sys/class/devfreq/.../available_governors shows
+ currently available governors in the system.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 45000f0db4d4..7fc2997b23a6 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -204,3 +204,34 @@ Description:
This attribute has no effect on system-wide suspend/resume and
hibernation.
+
+What: /sys/devices/.../power/pm_qos_no_power_off
+Date: September 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../power/pm_qos_no_power_off attribute
+ is used for manipulating the PM QoS "no power off" flag. If
+ set, this flag indicates to the kernel that power should not
+ be removed entirely from the device.
+
+ Not all drivers support this attribute. If it isn't supported,
+ it is not present.
+
+ This attribute has no effect on system-wide suspend/resume and
+ hibernation.
+
+What: /sys/devices/.../power/pm_qos_remote_wakeup
+Date: September 2012
+Contact: Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+ The /sys/devices/.../power/pm_qos_remote_wakeup attribute
+ is used for manipulating the PM QoS "remote wakeup required"
+ flag. If set, this flag indicates to the kernel that the
+ device is a source of user events that have to be signaled from
+ its low-power states.
+
+ Not all drivers support this attribute. If it isn't supported,
+ it is not present.
+
+ This attribute has no effect on system-wide suspend/resume and
+ hibernation.
diff --git a/Documentation/ABI/testing/sysfs-devices-sun b/Documentation/ABI/testing/sysfs-devices-sun
new file mode 100644
index 000000000000..86be9848a77e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-sun
@@ -0,0 +1,14 @@
+Whatt: /sys/devices/.../sun
+Date: October 2012
+Contact: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+Description:
+ The file contains a Slot-unique ID which provided by the _SUN
+ method in the ACPI namespace. The value is written in Advanced
+ Configuration and Power Interface Specification as follows:
+
+ "The _SUN value is required to be unique among the slots of
+ the same type. It is also recommended that this number match
+ the slot number printed on the physical slot whenever possible."
+
+ So reading the sysfs file, we can identify a physical position
+ of the slot in the system.
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index ac3d0018140c..ddb05e98af0d 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -719,6 +719,62 @@ framework to set up sysfs files for this region. Simply leave it alone.
</para>
</sect1>
+<sect1 id="using uio_dmem_genirq">
+<title>Using uio_dmem_genirq for platform devices</title>
+ <para>
+ In addition to statically allocated memory ranges, they may also be
+ a desire to use dynamically allocated regions in a user space driver.
+ In particular, being able to access memory made available through the
+ dma-mapping API, may be particularly useful. The
+ <varname>uio_dmem_genirq</varname> driver provides a way to accomplish
+ this.
+ </para>
+ <para>
+ This driver is used in a similar manner to the
+ <varname>"uio_pdrv_genirq"</varname> driver with respect to interrupt
+ configuration and handling.
+ </para>
+ <para>
+ Set the <varname>.name</varname> element of
+ <varname>struct platform_device</varname> to
+ <varname>"uio_dmem_genirq"</varname> to use this driver.
+ </para>
+ <para>
+ When using this driver, fill in the <varname>.platform_data</varname>
+ element of <varname>struct platform_device</varname>, which is of type
+ <varname>struct uio_dmem_genirq_pdata</varname> and which contains the
+ following elements:
+ </para>
+ <itemizedlist>
+ <listitem><varname>struct uio_info uioinfo</varname>: The same
+ structure used as the <varname>uio_pdrv_genirq</varname> platform
+ data</listitem>
+ <listitem><varname>unsigned int *dynamic_region_sizes</varname>:
+ Pointer to list of sizes of dynamic memory regions to be mapped into
+ user space.
+ </listitem>
+ <listitem><varname>unsigned int num_dynamic_regions</varname>:
+ Number of elements in <varname>dynamic_region_sizes</varname> array.
+ </listitem>
+ </itemizedlist>
+ <para>
+ The dynamic regions defined in the platform data will be appended to
+ the <varname> mem[] </varname> array after the platform device
+ resources, which implies that the total number of static and dynamic
+ memory regions cannot exceed <varname>MAX_UIO_MAPS</varname>.
+ </para>
+ <para>
+ The dynamic memory regions will be allocated when the UIO device file,
+ <varname>/dev/uioX</varname> is opened.
+ Simiar to static memory resources, the memory region information for
+ dynamic regions is then visible via sysfs at
+ <varname>/sys/class/uio/uioX/maps/mapY/*</varname>.
+ The dynmaic memory regions will be freed when the UIO device file is
+ closed. When no processes are holding the device file open, the address
+ returned to userspace is ~0.
+ </para>
+</sect1>
+
</chapter>
<chapter id="userspace_driver" xreflabel="Writing a driver in user space">
diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt
index 1401cece745a..9bc95942ec22 100644
--- a/Documentation/IRQ-domain.txt
+++ b/Documentation/IRQ-domain.txt
@@ -7,6 +7,21 @@ systems with multiple interrupt controllers the kernel must ensure
that each one gets assigned non-overlapping allocations of Linux
IRQ numbers.
+The number of interrupt controllers registered as unique irqchips
+show a rising tendency: for example subdrivers of different kinds
+such as GPIO controllers avoid reimplementing identical callback
+mechanisms as the IRQ core system by modelling their interrupt
+handlers as irqchips, i.e. in effect cascading interrupt controllers.
+
+Here the interrupt number loose all kind of correspondence to
+hardware interrupt numbers: whereas in the past, IRQ numbers could
+be chosen so they matched the hardware IRQ line into the root
+interrupt controller (i.e. the component actually fireing the
+interrupt line to the CPU) nowadays this number is just a number.
+
+For this reason we need a mechanism to separate controller-local
+interrupt numbers, called hardware irq's, from Linux IRQ numbers.
+
The irq_alloc_desc*() and irq_free_desc*() APIs provide allocation of
irq numbers, but they don't provide any support for reverse mapping of
the controller-local IRQ (hwirq) number into the Linux IRQ number
@@ -40,6 +55,10 @@ required hardware setup.
When an interrupt is received, irq_find_mapping() function should
be used to find the Linux IRQ number from the hwirq number.
+The irq_create_mapping() function must be called *atleast once*
+before any call to irq_find_mapping(), lest the descriptor will not
+be allocated.
+
If the driver has the Linux IRQ number or the irq_data pointer, and
needs to know the associated hwirq number (such as in the irq_chip
callbacks) then it can be directly obtained from irq_data->hwirq.
@@ -119,4 +138,17 @@ numbers.
Most users of legacy mappings should use irq_domain_add_simple() which
will use a legacy domain only if an IRQ range is supplied by the
-system and will otherwise use a linear domain mapping.
+system and will otherwise use a linear domain mapping. The semantics
+of this call are such that if an IRQ range is specified then
+descriptors will be allocated on-the-fly for it, and if no range is
+specified it will fall through to irq_domain_add_linear() which meand
+*no* irq descriptors will be allocated.
+
+A typical use case for simple domains is where an irqchip provider
+is supporting both dynamic and static IRQ assignments.
+
+In order to avoid ending up in a situation where a linear domain is
+used and no descriptor gets allocated it is very important to make sure
+that the driver using the simple domain call irq_create_mapping()
+before any irq_find_mapping() since the latter will actually work
+for the static IRQ assignment case.
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
new file mode 100644
index 000000000000..4f27785ca0c8
--- /dev/null
+++ b/Documentation/acpi/enumeration.txt
@@ -0,0 +1,227 @@
+ACPI based device enumeration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ACPI 5 introduced a set of new resources (UartTSerialBus, I2cSerialBus,
+SpiSerialBus, GpioIo and GpioInt) which can be used in enumerating slave
+devices behind serial bus controllers.
+
+In addition we are starting to see peripherals integrated in the
+SoC/Chipset to appear only in ACPI namespace. These are typically devices
+that are accessed through memory-mapped registers.
+
+In order to support this and re-use the existing drivers as much as
+possible we decided to do following:
+
+ o Devices that have no bus connector resource are represented as
+ platform devices.
+
+ o Devices behind real busses where there is a connector resource
+ are represented as struct spi_device or struct i2c_device
+ (standard UARTs are not busses so there is no struct uart_device).
+
+As both ACPI and Device Tree represent a tree of devices (and their
+resources) this implementation follows the Device Tree way as much as
+possible.
+
+The ACPI implementation enumerates devices behind busses (platform, SPI and
+I2C), creates the physical devices and binds them to their ACPI handle in
+the ACPI namespace.
+
+This means that when ACPI_HANDLE(dev) returns non-NULL the device was
+enumerated from ACPI namespace. This handle can be used to extract other
+device-specific configuration. There is an example of this below.
+
+Platform bus support
+~~~~~~~~~~~~~~~~~~~~
+Since we are using platform devices to represent devices that are not
+connected to any physical bus we only need to implement a platform driver
+for the device and add supported ACPI IDs. If this same IP-block is used on
+some other non-ACPI platform, the driver might work out of the box or needs
+some minor changes.
+
+Adding ACPI support for an existing driver should be pretty
+straightforward. Here is the simplest example:
+
+ #ifdef CONFIG_ACPI
+ static struct acpi_device_id mydrv_acpi_match[] = {
+ /* ACPI IDs here */
+ { }
+ };
+ MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match);
+ #endif
+
+ static struct platform_driver my_driver = {
+ ...
+ .driver = {
+ .acpi_match_table = ACPI_PTR(mydrv_acpi_match),
+ },
+ };
+
+If the driver needs to perform more complex initialization like getting and
+configuring GPIOs it can get its ACPI handle and extract this information
+from ACPI tables.
+
+Currently the kernel is not able to automatically determine from which ACPI
+device it should make the corresponding platform device so we need to add
+the ACPI device explicitly to acpi_platform_device_ids list defined in
+drivers/acpi/scan.c. This limitation is only for the platform devices, SPI
+and I2C devices are created automatically as described below.
+
+SPI serial bus support
+~~~~~~~~~~~~~~~~~~~~~~
+Slave devices behind SPI bus have SpiSerialBus resource attached to them.
+This is extracted automatically by the SPI core and the slave devices are
+enumerated once spi_register_master() is called by the bus driver.
+
+Here is what the ACPI namespace for a SPI slave might look like:
+
+ Device (EEP0)
+ {
+ Name (_ADR, 1)
+ Name (_CID, Package() {
+ "ATML0025",
+ "AT25",
+ })
+ ...
+ Method (_CRS, 0, NotSerialized)
+ {
+ SPISerialBus(1, PolarityLow, FourWireMode, 8,
+ ControllerInitiated, 1000000, ClockPolarityLow,
+ ClockPhaseFirst, "\\_SB.PCI0.SPI1",)
+ }
+ ...
+
+The SPI device drivers only need to add ACPI IDs in a similar way than with
+the platform device drivers. Below is an example where we add ACPI support
+to at25 SPI eeprom driver (this is meant for the above ACPI snippet):
+
+ #ifdef CONFIG_ACPI
+ static struct acpi_device_id at25_acpi_match[] = {
+ { "AT25", 0 },
+ { },
+ };
+ MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
+ #endif
+
+ static struct spi_driver at25_driver = {
+ .driver = {
+ ...
+ .acpi_match_table = ACPI_PTR(at25_acpi_match),
+ },
+ };
+
+Note that this driver actually needs more information like page size of the
+eeprom etc. but at the time writing this there is no standard way of
+passing those. One idea is to return this in _DSM method like:
+
+ Device (EEP0)
+ {
+ ...
+ Method (_DSM, 4, NotSerialized)
+ {
+ Store (Package (6)
+ {
+ "byte-len", 1024,
+ "addr-mode", 2,
+ "page-size, 32
+ }, Local0)
+
+ // Check UUIDs etc.
+
+ Return (Local0)
+ }
+
+Then the at25 SPI driver can get this configation by calling _DSM on its
+ACPI handle like:
+
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_object_list input;
+ acpi_status status;
+
+ /* Fill in the input buffer */
+
+ status = acpi_evaluate_object(ACPI_HANDLE(&spi->dev), "_DSM",
+ &input, &output);
+ if (ACPI_FAILURE(status))
+ /* Handle the error */
+
+ /* Extract the data here */
+
+ kfree(output.pointer);
+
+I2C serial bus support
+~~~~~~~~~~~~~~~~~~~~~~
+The slaves behind I2C bus controller only need to add the ACPI IDs like
+with the platform and SPI drivers. However the I2C bus controller driver
+needs to call acpi_i2c_register_devices() after it has added the adapter.
+
+An I2C bus (controller) driver does:
+
+ ...
+ ret = i2c_add_numbered_adapter(adapter);
+ if (ret)
+ /* handle error */
+
+ of_i2c_register_devices(adapter);
+ /* Enumerate the slave devices behind this bus via ACPI */
+ acpi_i2c_register_devices(adapter);
+
+Below is an example of how to add ACPI support to the existing mpu3050
+input driver:
+
+ #ifdef CONFIG_ACPI
+ static struct acpi_device_id mpu3050_acpi_match[] = {
+ { "MPU3050", 0 },
+ { },
+ };
+ MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match);
+ #endif
+
+ static struct i2c_driver mpu3050_i2c_driver = {
+ .driver = {
+ .name = "mpu3050",
+ .owner = THIS_MODULE,
+ .pm = &mpu3050_pm,
+ .of_match_table = mpu3050_of_match,
+ .acpi_match_table ACPI_PTR(mpu3050_acpi_match),
+ },
+ .probe = mpu3050_probe,
+ .remove = __devexit_p(mpu3050_remove),
+ .id_table = mpu3050_ids,
+ };
+
+GPIO support
+~~~~~~~~~~~~
+ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
+and GpioInt. These resources are used be used to pass GPIO numbers used by
+the device to the driver. For example:
+
+ Method (_CRS, 0, NotSerialized)
+ {
+ Name (SBUF, ResourceTemplate()
+ {
+ GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+ IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
+ 0x00, ResourceConsumer,,)
+ {
+ // Pin List
+ 0x0055
+ }
+ ...
+
+ Return (SBUF)
+ }
+ }
+
+These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
+specifies the path to the controller. In order to use these GPIOs in Linux
+we need to translate them to the Linux GPIO numbers.
+
+The driver can do this by including <linux/acpi_gpio.h> and then calling
+acpi_get_gpio(path, gpio). This will return the Linux GPIO number or
+negative errno if there was no translation found.
+
+Other GpioIo parameters must be converted first by the driver to be
+suitable to the gpiolib before passing them.
+
+In case of GpioInt resource an additional call to gpio_to_irq() must be
+done before calling request_irq().
diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt
index d187e9f7cf1c..1196290082d1 100644
--- a/Documentation/devicetree/bindings/arm/atmel-at91.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt
@@ -7,6 +7,12 @@ PIT Timer required properties:
- interrupts: Should contain interrupt for the PIT which is the IRQ line
shared across all System Controller members.
+System Timer (ST) required properties:
+- compatible: Should be "atmel,at91rm9200-st"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt for the ST which is the IRQ line
+ shared across all System Controller members.
+
TC/TCLIB Timer required properties:
- compatible: Should be "atmel,<chip>-tcb".
<chip> can be "at91rm9200" or "at91sam9x5"
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
index e37241f1fdd8..49fc7ada929a 100644
--- a/Documentation/devicetree/bindings/arm/davinci/nand.txt
+++ b/Documentation/devicetree/bindings/arm/davinci/nand.txt
@@ -23,29 +23,16 @@ Recommended properties :
- ti,davinci-nand-buswidth: buswidth 8 or 16
- ti,davinci-nand-use-bbt: use flash based bad block table support.
-Example (enbw_cmc board):
-aemif@60000000 {
- compatible = "ti,davinci-aemif";
- #address-cells = <2>;
- #size-cells = <1>;
- reg = <0x68000000 0x80000>;
- ranges = <2 0 0x60000000 0x02000000
- 3 0 0x62000000 0x02000000
- 4 0 0x64000000 0x02000000
- 5 0 0x66000000 0x02000000
- 6 0 0x68000000 0x02000000>;
- nand@3,0 {
- compatible = "ti,davinci-nand";
- reg = <3 0x0 0x807ff
- 6 0x0 0x8000>;
- #address-cells = <1>;
- #size-cells = <1>;
- ti,davinci-chipselect = <1>;
- ti,davinci-mask-ale = <0>;
- ti,davinci-mask-cle = <0>;
- ti,davinci-mask-chipsel = <0>;
- ti,davinci-ecc-mode = "hw";
- ti,davinci-ecc-bits = <4>;
- ti,davinci-nand-use-bbt;
- };
+Example(da850 EVM ):
+nand_cs3@62000000 {
+ compatible = "ti,davinci-nand";
+ reg = <0x62000000 0x807ff
+ 0x68000000 0x8000>;
+ ti,davinci-chipselect = <1>;
+ ti,davinci-mask-ale = <0>;
+ ti,davinci-mask-cle = <0>;
+ ti,davinci-mask-chipsel = <0>;
+ ti,davinci-ecc-mode = "hw";
+ ti,davinci-ecc-bits = <4>;
+ ti,davinci-nand-use-bbt;
};
diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt
index 7ca52161e7ab..7c3ee3aeb7b7 100644
--- a/Documentation/devicetree/bindings/arm/l2cc.txt
+++ b/Documentation/devicetree/bindings/arm/l2cc.txt
@@ -37,7 +37,7 @@ L2: cache-controller {
reg = <0xfff12000 0x1000>;
arm,data-latency = <1 1 1>;
arm,tag-latency = <2 2 2>;
- arm,filter-latency = <0x80000000 0x8000000>;
+ arm,filter-ranges = <0x80000000 0x8000000>;
cache-unified;
cache-level = <2>;
interrupts = <45>;
diff --git a/Documentation/devicetree/bindings/clock/imx23-clock.txt b/Documentation/devicetree/bindings/clock/imx23-clock.txt
index a0b867ef8d96..baadbb11fe98 100644
--- a/Documentation/devicetree/bindings/clock/imx23-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx23-clock.txt
@@ -52,7 +52,7 @@ clocks and IDs.
lcdif 38
etm 39
usb 40
- usb_pwr 41
+ usb_phy 41
Examples:
diff --git a/Documentation/devicetree/bindings/clock/imx28-clock.txt b/Documentation/devicetree/bindings/clock/imx28-clock.txt
index aa2af2866fe8..52a49a4a50b3 100644
--- a/Documentation/devicetree/bindings/clock/imx28-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx28-clock.txt
@@ -73,8 +73,8 @@ clocks and IDs.
can1 59
usb0 60
usb1 61
- usb0_pwr 62
- usb1_pwr 63
+ usb0_phy 62
+ usb1_phy 63
enet_out 64
Examples:
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
new file mode 100644
index 000000000000..f3d44984d91c
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
@@ -0,0 +1,42 @@
+SPEAr cpufreq driver
+-------------------
+
+SPEAr SoC cpufreq driver for CPU frequency scaling.
+It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) systems
+which share clock across all CPUs.
+
+Required properties:
+- cpufreq_tbl: Table of frequencies CPU could be transitioned into, in the
+ increasing order.
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock, in
+ unit of nanoseconds.
+
+Both required and optional properties listed above must be defined under node
+/cpus/cpu@0.
+
+Examples:
+--------
+cpus {
+
+ <...>
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+
+ <...>
+
+ cpufreq_tbl = < 166000
+ 200000
+ 250000
+ 300000
+ 400000
+ 500000
+ 600000 >;
+ };
+
+ <...>
+
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt
new file mode 100644
index 000000000000..a0e4cf885213
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-stmpe.txt
@@ -0,0 +1,18 @@
+STMPE gpio
+----------
+
+Required properties:
+ - compatible: "st,stmpe-gpio"
+
+Optional properties:
+ - st,norequest-mask: bitmask specifying which GPIOs should _not_ be requestable
+ due to different usage (e.g. touch, keypad)
+
+Node name must be stmpe_gpio and should be child node of stmpe node to which it
+belongs.
+
+Example:
+ stmpe_gpio {
+ compatible = "st,stmpe-gpio";
+ st,norequest-mask = <0x20>; //gpio 5 can't be used
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 4e16ba4feab0..a33628759d36 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
gpio-controller;
};
+2.1) gpio-controller and pinctrl subsystem
+------------------------------------------
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can use a pinctrl phandle and pins to
+announce the pinrange to the pin ctrl subsystem. For example,
+
+ qe_pio_e: gpio-controller@1460 {
+ #gpio-cells = <2>;
+ compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+ reg = <0x1460 0x18>;
+ gpio-controller;
+ gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+
+ }
+
+where,
+ &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
+
+ Next values specify the base pin and number of pins for the range
+ handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
+ pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
+ by this gpio controller.
+
+The pinctrl node must have "#gpio-range-cells" property to show number of
+arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
index 66efc804806a..85f8c0d084fa 100644
--- a/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio_atmel.txt
@@ -9,6 +9,10 @@ Required properties:
unused).
- gpio-controller: Marks the device node as a GPIO controller.
+optional properties:
+- #gpio-lines: Number of gpio if absent 32.
+
+
Example:
pioA: gpio@fffff200 {
compatible = "atmel,at91rm9200-gpio";
@@ -16,5 +20,6 @@ Example:
interrupts = <2 4>;
#gpio-cells = <2>;
gpio-controller;
+ #gpio-lines = <19>;
};
diff --git a/Documentation/devicetree/bindings/gpio/spear_spics.txt b/Documentation/devicetree/bindings/gpio/spear_spics.txt
new file mode 100644
index 000000000000..96c37eb15075
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/spear_spics.txt
@@ -0,0 +1,50 @@
+=== ST Microelectronics SPEAr SPI CS Driver ===
+
+SPEAr platform provides a provision to control chipselects of ARM PL022 Prime
+Cell spi controller through its system registers, which otherwise remains under
+PL022 control. If chipselect remain under PL022 control then they would be
+released as soon as transfer is over and TxFIFO becomes empty. This is not
+desired by some of the device protocols above spi which expect (multiple)
+transfers without releasing their chipselects.
+
+Chipselects can be controlled by software by turning them as GPIOs. SPEAr
+provides another interface through system registers through which software can
+directly control each PL022 chipselect. Hence, it is natural for SPEAr to export
+the control of this interface as gpio.
+
+Required properties:
+
+ * compatible: should be defined as "st,spear-spics-gpio"
+ * reg: mentioning address range of spics controller
+ * st-spics,peripcfg-reg: peripheral configuration register offset
+ * st-spics,sw-enable-bit: bit offset to enable sw control
+ * st-spics,cs-value-bit: bit offset to drive chipselect low or high
+ * st-spics,cs-enable-mask: chip select number bit mask
+ * st-spics,cs-enable-shift: chip select number program offset
+ * gpio-controller: Marks the device node as gpio controller
+ * #gpio-cells: should be 1 and will mention chip select number
+
+All the above bit offsets are within peripcfg register.
+
+Example:
+-------
+spics: spics@e0700000{
+ compatible = "st,spear-spics-gpio";
+ reg = <0xe0700000 0x1000>;
+ st-spics,peripcfg-reg = <0x3b0>;
+ st-spics,sw-enable-bit = <12>;
+ st-spics,cs-value-bit = <11>;
+ st-spics,cs-enable-mask = <3>;
+ st-spics,cs-enable-shift = <8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+
+spi0: spi@e0100000 {
+ status = "okay";
+ num-cs = <3>;
+ cs-gpios = <&gpio1 7 0>, <&spics 0>,
+ <&spics 1>;
+ ...
+}
diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-at91.txt
index b689a0d9441c..b689a0d9441c 100644
--- a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-at91.txt
diff --git a/Documentation/devicetree/bindings/i2c/davinci.txt b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
index 2dc935b4113d..2dc935b4113d 100644
--- a/Documentation/devicetree/bindings/i2c/davinci.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
diff --git a/Documentation/devicetree/bindings/i2c/gpio-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-gpio.txt
index 4f8ec947c6bd..4f8ec947c6bd 100644
--- a/Documentation/devicetree/bindings/i2c/gpio-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-gpio.txt
diff --git a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
index f3cf43b66f7e..f3cf43b66f7e 100644
--- a/Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
diff --git a/Documentation/devicetree/bindings/i2c/fsl-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt
index 1eacd6b20ed5..1eacd6b20ed5 100644
--- a/Documentation/devicetree/bindings/i2c/fsl-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt
diff --git a/Documentation/devicetree/bindings/i2c/mux.txt b/Documentation/devicetree/bindings/i2c/i2c-mux.txt
index af84cce5cd7b..af84cce5cd7b 100644
--- a/Documentation/devicetree/bindings/i2c/mux.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux.txt
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
new file mode 100644
index 000000000000..f46d928aa73d
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
@@ -0,0 +1,18 @@
+
+* Marvell MV64XXX I2C controller
+
+Required properties :
+
+ - reg : Offset and length of the register set for the device
+ - compatible : Should be "marvell,mv64xxx-i2c"
+ - interrupts : The interrupt number
+ - clock-frequency : Desired I2C bus clock frequency in Hz.
+
+Examples:
+
+ i2c@11000 {
+ compatible = "marvell,mv64xxx-i2c";
+ reg = <0x11000 0x20>;
+ interrupts = <29>;
+ clock-frequency = <100000>;
+ };
diff --git a/Documentation/devicetree/bindings/i2c/nomadik.txt b/Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
index 72065b0ff680..72065b0ff680 100644
--- a/Documentation/devicetree/bindings/i2c/nomadik.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-nomadik.txt
diff --git a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
index dced82ebe31d..dced82ebe31d 100644
--- a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
diff --git a/Documentation/devicetree/bindings/i2c/omap-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
index 56564aa4b444..56564aa4b444 100644
--- a/Documentation/devicetree/bindings/i2c/omap-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
diff --git a/Documentation/devicetree/bindings/i2c/pnx.txt b/Documentation/devicetree/bindings/i2c/i2c-pnx.txt
index fe98ada33ee4..fe98ada33ee4 100644
--- a/Documentation/devicetree/bindings/i2c/pnx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pnx.txt
diff --git a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt
index 569b16248514..569b16248514 100644
--- a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt
diff --git a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
index 0f7945019f6f..12b78ac507e9 100644
--- a/Documentation/devicetree/bindings/i2c/mrvl-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
@@ -31,21 +31,3 @@ Examples:
reg = <0xd4025000 0x1000>;
interrupts = <58>;
};
-
-* Marvell MV64XXX I2C controller
-
-Required properties :
-
- - reg : Offset and length of the register set for the device
- - compatible : Should be "marvell,mv64xxx-i2c"
- - interrupts : The interrupt number
- - clock-frequency : Desired I2C bus clock frequency in Hz.
-
-Examples:
-
- i2c@11000 {
- compatible = "marvell,mv64xxx-i2c";
- reg = <0x11000 0x20>;
- interrupts = <29>;
- clock-frequency = <100000>;
- };
diff --git a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
index b6cb5a12c672..b6cb5a12c672 100644
--- a/Documentation/devicetree/bindings/i2c/samsung-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
diff --git a/Documentation/devicetree/bindings/i2c/sirf-i2c.txt b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
index 7baf9e133fa8..7baf9e133fa8 100644
--- a/Documentation/devicetree/bindings/i2c/sirf-i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
diff --git a/Documentation/devicetree/bindings/i2c/arm-versatile.txt b/Documentation/devicetree/bindings/i2c/i2c-versatile.txt
index 361d31c51b6f..361d31c51b6f 100644
--- a/Documentation/devicetree/bindings/i2c/arm-versatile.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-versatile.txt
diff --git a/Documentation/devicetree/bindings/i2c/xiic.txt b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt
index ceabbe91ae44..ceabbe91ae44 100644
--- a/Documentation/devicetree/bindings/i2c/xiic.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-xiic.txt
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
new file mode 100644
index 000000000000..2d88816dd550
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/common.txt
@@ -0,0 +1,23 @@
+Common leds properties.
+
+Optional properties for child nodes:
+- label : The label for this LED. If omitted, the label is
+ taken from the node name (excluding the unit address).
+
+- linux,default-trigger : This parameter, if present, is a
+ string defining the trigger assigned to the LED. Current triggers are:
+ "backlight" - LED will act as a back-light, controlled by the framebuffer
+ system
+ "default-on" - LED will turn on (but for leds-gpio see "default-state"
+ property in Documentation/devicetree/bindings/gpio/led.txt)
+ "heartbeat" - LED "double" flashes at a load average based rate
+ "ide-disk" - LED indicates disk activity
+ "timer" - LED flashes at a fixed, configurable rate
+
+Examples:
+
+system-status {
+ label = "Status";
+ linux,default-trigger = "heartbeat";
+ ...
+};
diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt
index edc83c1c0d54..df1b3080f6b8 100644
--- a/Documentation/devicetree/bindings/gpio/led.txt
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt
@@ -10,16 +10,10 @@ LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "gpios property" in
Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be
indicated using flags in the GPIO specifier.
-- label : (optional) The label for this LED. If omitted, the label is
- taken from the node name (excluding the unit address).
-- linux,default-trigger : (optional) This parameter, if present, is a
- string defining the trigger assigned to the LED. Current triggers are:
- "backlight" - LED will act as a back-light, controlled by the framebuffer
- system
- "default-on" - LED will turn on, but see "default-state" below
- "heartbeat" - LED "double" flashes at a load average based rate
- "ide-disk" - LED indicates disk activity
- "timer" - LED flashes at a fixed, configurable rate
+- label : (optional)
+ see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger : (optional)
+ see Documentation/devicetree/bindings/leds/common.txt
- default-state: (optional) The initial state of the LED. Valid
values are "on", "off", and "keep". If the LED is already on or off
and the default-state property is set the to same value, then no
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 8e2e0ba2f486..a591c6741d75 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -21,6 +21,12 @@ Optional properties:
- cd-inverted: when present, polarity on the cd gpio line is inverted
- wp-inverted: when present, polarity on the wp gpio line is inverted
- max-frequency: maximum operating clock frequency
+- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on
+ this system, even if the controller claims it is.
+
+Optional SDIO properties:
+- keep-power-in-suspend: Preserves card power during a suspend/resume cycle
+- enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion
Example:
@@ -33,4 +39,6 @@ sdhci@ab000000 {
cd-inverted;
wp-gpios = <&gpio 70 0>;
max-frequency = <50000000>;
+ keep-power-in-suspend;
+ enable-sdio-wakeup;
}
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
index 630a7d7f4718..97e9e315400d 100644
--- a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
+++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
@@ -12,10 +12,6 @@ is used. The Samsung's SDHCI controller bindings extends this as listed below.
[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
"Optional Board Specific Properties" section below.
-[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
- is not specified, it is assumed that there is no card detection
- mechanism used.
-
Required SoC Specific Properties:
- compatible: should be one of the following
- "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
@@ -24,14 +20,18 @@ Required SoC Specific Properties:
controller.
Required Board Specific Properties:
-- gpios: Should specify the gpios used for clock, command and data lines. The
- gpio specifier format depends on the gpio controller.
+- Samsung GPIO variant (will be completely replaced by pinctrl):
+ - gpios: Should specify the gpios used for clock, command and data lines. The
+ gpio specifier format depends on the gpio controller.
+- Pinctrl variant (preferred if available):
+ - pinctrl-0: Should specify pin control groups used for this controller.
+ - pinctrl-names: Should contain only one value - "default".
Optional Board Specific Properties:
- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
through a pinmux to the card-detect pin of the card slot. This property
should be used only if none of the mmc core card-detect properties are
- used.
+ used. Only for Samsung GPIO variant.
Example:
sdhci@12530000 {
@@ -40,12 +40,18 @@ Example:
interrupts = <0 75 0>;
bus-width = <4>;
cd-gpios = <&gpk2 2 2 3 3>;
+
+ /* Samsung GPIO variant */
gpios = <&gpk2 0 2 0 3>, /* clock line */
<&gpk2 1 2 0 3>, /* command line */
<&gpk2 3 2 3 3>, /* data line 0 */
<&gpk2 4 2 3 3>, /* data line 1 */
<&gpk2 5 2 3 3>, /* data line 2 */
<&gpk2 6 2 3 3>; /* data line 3 */
+
+ /* Pinctrl variant */
+ pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+ pinctrl-names = "default";
};
Note: This example shows both SoC specific and board specific properties
diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
index 06cd32d08052..06cd32d08052 100644
--- a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index be76a23b34c4..ed271fc255b2 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -19,6 +19,7 @@ ti,dual-volt: boolean, supports dual voltage cards
"supply-name" examples are "vmmc", "vmmc_aux" etc
ti,non-removable: non-removable slot (like eMMC)
ti,needs-special-reset: Requires a special softreset sequence
+ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
Example:
mmc1: mmc@0x4809c000 {
diff --git a/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt b/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
new file mode 100644
index 000000000000..d7fb6abb3eb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
@@ -0,0 +1,23 @@
+* Wondermedia WM8505/WM8650 SD/MMC Host Controller
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the wmt-sdmmc driver.
+
+Required properties:
+- compatible: Should be "wm,wm8505-sdhc".
+- interrupts: Two interrupts are required - regular irq and dma irq.
+
+Optional properties:
+- sdon-inverted: SD_ON bit is inverted on the controller
+
+Examples:
+
+sdhc@d800a000 {
+ compatible = "wm,wm8505-sdhc";
+ reg = <0xd800a000 0x1000>;
+ interrupts = <20 21>;
+ clocks = <&sdhc>;
+ bus-width = <4>;
+ sdon-inverted;
+};
+
diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt
index bc9549529014..c79bab025369 100644
--- a/Documentation/devicetree/bindings/net/mdio-gpio.txt
+++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt
@@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order:
MDC, MDIO.
+Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases"
+node.
+
Example:
-mdio {
+aliases {
+ mdio-gpio0 = <&mdio0>;
+};
+
+mdio0: mdio {
compatible = "virtual,mdio-gpio";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
new file mode 100644
index 000000000000..3a268127b054
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -0,0 +1,141 @@
+* Atmel AT91 Pinmux Controller
+
+The AT91 Pinmux Controler, 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 periph modes). Since different modules require
+different PAD settings (like pull up, keeper, etc) the contoller 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".
+
+Atmel AT91 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 'pins' selects the function mode(also named pin
+mode) this pin can work on and the 'config' configures various pad settings
+such as pull-up, multi drive, etc.
+
+Required properties for iomux controller:
+- compatible: "atmel,at91rm9200-pinctrl"
+- atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
+ configured in this periph mode. All the periph and bank need to be describe.
+
+How to create such array:
+
+Each column will represent the possible peripheral of the pinctrl
+Each line will represent a pio bank
+
+Take an example on the 9260
+Peripheral: 2 ( A and B)
+Bank: 3 (A, B and C)
+=>
+
+ /* A B */
+ 0xffffffff 0xffc00c3b /* pioA */
+ 0xffffffff 0x7fff3ccf /* pioB */
+ 0xffffffff 0x007fffff /* pioC */
+
+For each peripheral/bank we will descibe in a u32 if a pin can can be
+configured in it by putting 1 to the pin bit (1 << pin)
+
+Let's take the pioA on peripheral B
+From the datasheet Table 10-2.
+Peripheral B
+PA0 MCDB0
+PA1 MCCDB
+PA2
+PA3 MCDB3
+PA4 MCDB2
+PA5 MCDB1
+PA6
+PA7
+PA8
+PA9
+PA10 ETX2
+PA11 ETX3
+PA12
+PA13
+PA14
+PA15
+PA16
+PA17
+PA18
+PA19
+PA20
+PA21
+PA22 ETXER
+PA23 ETX2
+PA24 ETX3
+PA25 ERX2
+PA26 ERX3
+PA27 ERXCK
+PA28 ECRS
+PA29 ECOL
+PA30 RXD4
+PA31 TXD4
+
+=> 0xffc00c3b
+
+Required properties for pin configuration node:
+- atmel,pins: 4 integers array, represents a group of pins mux and config
+ setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
+ The PERIPH 0 means gpio.
+
+Bits used for CONFIG:
+PULL_UP (1 << 0): indicate this pin need a pull up.
+MULTIDRIVE (1 << 1): indicate this pin need to be configured as multidrive.
+DEGLITCH (1 << 2): indicate this pin need deglitch.
+PULL_DOWN (1 << 3): indicate this pin need a pull down.
+DIS_SCHMIT (1 << 4): indicate this pin need to disable schmit trigger.
+DEBOUNCE (1 << 16): indicate this pin need debounce.
+DEBOUNCE_VAL (0x3fff << 17): debounce val.
+
+NOTE:
+Some requirements for using atmel,at91rm9200-pinctrl binding:
+1. We have pin function node defined under at91 controller node to represent
+ what pinmux functions this SoC supports.
+2. 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 at91 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.
+3. Each pin configuration node should have a phandle, devices can set pins
+ configurations by referring to the phandle of that pin configuration node.
+4. The gpio controller must be describe in the pinctrl simple-bus.
+
+Examples:
+
+pinctrl@fffff400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+ reg = <0xfffff400 0x600>;
+
+ atmel,mux-mask = <
+ /* A B */
+ 0xffffffff 0xffc00c3b /* pioA */
+ 0xffffffff 0x7fff3ccf /* pioB */
+ 0xffffffff 0x007fffff /* pioC */
+ >;
+
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <1 14 0x1 0x0 /* PB14 periph A */
+ 1 15 0x1 0x1>; /* PB15 periph with pullup */
+ };
+ };
+};
+
+dbgu: serial@fffff200 {
+ compatible = "atmel,at91sam9260-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
+ status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/rtc/orion-rtc.txt b/Documentation/devicetree/bindings/rtc/orion-rtc.txt
new file mode 100644
index 000000000000..3bf63ffa5160
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/orion-rtc.txt
@@ -0,0 +1,18 @@
+* Mvebu Real Time Clock
+
+RTC controller for the Kirkwood, the Dove, the Armada 370 and the
+Armada XP SoCs
+
+Required properties:
+- compatible : Should be "marvell,orion-rtc"
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: IRQ line for the RTC.
+
+Example:
+
+rtc@10300 {
+ compatible = "marvell,orion-rtc";
+ reg = <0xd0010300 0x20>;
+ interrupts = <50>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 9de2b9ff9d6e..770a0193ca1b 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -5,6 +5,7 @@ using them to avoid name-space collisions.
ad Avionic Design GmbH
adi Analog Devices, Inc.
+ak Asahi Kasei Corp.
amcc Applied Micro Circuits Corporation (APM, formally AMCC)
apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd.
@@ -25,6 +26,7 @@ gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.
hp Hewlett Packard
ibm International Business Machines (IBM)
idt Integrated Device Technologies, Inc.
+img Imagination Technologies Ltd.
intercontrol Inter Control Group
linux Linux-specific binding
marvell Marvell Technology Group Ltd.
@@ -34,8 +36,9 @@ national National Semiconductor
nintendo Nintendo
nvidia NVIDIA
nxp NXP Semiconductors
+onnn ON Semiconductor Corp.
picochip Picochip Ltd
-powervr Imagination Technologies
+powervr PowerVR (deprecated, use img)
qcom Qualcomm, Inc.
ramtron Ramtron International
realtek Realtek Semiconductor Corp.
@@ -45,6 +48,7 @@ schindler Schindler
sil Silicon Image
simtek
sirf SiRF Technology, Inc.
+snps Synopsys, Inc.
st STMicroelectronics
stericsson ST-Ericsson
ti Texas Instruments
diff --git a/Documentation/devicetree/usage-model.txt b/Documentation/devicetree/usage-model.txt
index dca90fe22a90..ef9d06c9f8fd 100644
--- a/Documentation/devicetree/usage-model.txt
+++ b/Documentation/devicetree/usage-model.txt
@@ -347,7 +347,7 @@ later), which will happily live at the base of the Linux /sys/devices
tree. Therefore, if a DT node is at the root of the tree, then it
really probably is best registered as a platform_device.
-Linux board support code calls of_platform_populate(NULL, NULL, NULL)
+Linux board support code calls of_platform_populate(NULL, NULL, NULL, NULL)
to kick off discovery of devices at the root of the tree. The
parameters are all NULL because when starting from the root of the
tree, there is no need to provide a starting node (the first NULL), a
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index 815b711bcd85..43fada989e65 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -22,12 +22,17 @@
- calls request_firmware(&fw_entry, $FIRMWARE, device)
- kernel searchs the fimware image with name $FIRMWARE directly
in the below search path of root filesystem:
+ User customized search path by module parameter 'path'[1]
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
"/lib/firmware"
- If found, goto 7), else goto 2)
+ [1], the 'path' is a string parameter which length should be less
+ than 256, user should pass 'firmware_class.path=$CUSTOMIZED_PATH'
+ if firmware_class is built in kernel(the general situation)
+
2), userspace:
- /sys/class/firmware/xxx/{loading,data} appear.
- hotplug gets called with a firmware identifier in $FIRMWARE
@@ -114,3 +119,10 @@
on the setup, so I think that the choice on what firmware to make
persistent should be left to userspace.
+ about firmware cache:
+ --------------------
+ After firmware cache mechanism is introduced during system sleep,
+ request_firmware can be called safely inside device's suspend and
+ resume callback, and callers need't cache the firmware by
+ themselves any more for dealing with firmware loss during system
+ resume.
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e08a883de36e..77a1d11af723 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
signaling rate accordingly.
+GPIO controllers and the pinctrl subsystem
+------------------------------------------
+
+A GPIO controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with an optional gpio feature. We have already covered the
+case where e.g. a GPIO controller need to reserve a pin or set the
+direction of a pin by calling any of:
+
+pinctrl_request_gpio()
+pinctrl_free_gpio()
+pinctrl_gpio_direction_input()
+pinctrl_gpio_direction_output()
+
+But how does the pin control subsystem cross-correlate the GPIO
+numbers (which are a global business) to a certain pin on a certain
+pin controller?
+
+This is done by registering "ranges" of pins, which are essentially
+cross-reference tables. These are described in
+Documentation/pinctrl.txt
+
+While the pin allocation is totally managed by the pinctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
+to request the corresponding pin to be prepared by the pinctrl subsystem
+before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl
+subsystem. There are two ways of doing it currently: with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the
+argument to this routine.
+
+
What do these conventions omit?
===============================
One of the biggest things these conventions omit is pin multiplexing, since
diff --git a/Documentation/hwmon/ads7828 b/Documentation/hwmon/ads7828
index 2bbebe6f771f..f6e263e0f607 100644
--- a/Documentation/hwmon/ads7828
+++ b/Documentation/hwmon/ads7828
@@ -4,29 +4,47 @@ Kernel driver ads7828
Supported chips:
* Texas Instruments/Burr-Brown ADS7828
Prefix: 'ads7828'
- Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4b
- Datasheet: Publicly available at the Texas Instruments website :
+ Datasheet: Publicly available at the Texas Instruments website:
http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+ * Texas Instruments ADS7830
+ Prefix: 'ads7830'
+ Datasheet: Publicly available at the Texas Instruments website:
+ http://focus.ti.com/lit/ds/symlink/ads7830.pdf
+
Authors:
Steve Hardy <shardy@redhat.com>
+ Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+
+Platform data
+-------------
+
+The ads7828 driver accepts an optional ads7828_platform_data structure (defined
+in include/linux/platform_data/ads7828.h). The structure fields are:
-Module Parameters
------------------
+* diff_input: (bool) Differential operation
+ set to true for differential mode, false for default single ended mode.
-* se_input: bool (default Y)
- Single ended operation - set to N for differential mode
-* int_vref: bool (default Y)
- Operate with the internal 2.5V reference - set to N for external reference
-* vref_mv: int (default 2500)
- If using an external reference, set this to the reference voltage in mV
+* ext_vref: (bool) External reference
+ set to true if it operates with an external reference, false for default
+ internal reference.
+
+* vref_mv: (unsigned int) Voltage reference
+ if using an external reference, set this to the reference voltage in mV,
+ otherwise it will default to the internal value (2500mV). This value will be
+ bounded with limits accepted by the chip, described in the datasheet.
+
+ If no structure is provided, the configuration defaults to single ended
+ operation and internal voltage reference (2.5V).
Description
-----------
-This driver implements support for the Texas Instruments ADS7828.
+This driver implements support for the Texas Instruments ADS7828 and ADS7830.
-This device is a 12-bit 8-channel A-D converter.
+The ADS7828 device is a 12-bit 8-channel A/D converter, while the ADS7830 does
+8-bit sampling.
It can operate in single ended mode (8 +ve inputs) or in differential mode,
where 4 differential pairs can be measured.
@@ -34,3 +52,7 @@ where 4 differential pairs can be measured.
The chip also has the facility to use an external voltage reference. This
may be required if your hardware supplies the ADS7828 from a 5V supply, see
the datasheet for more details.
+
+There is no reliable way to identify this chip, so the driver will not scan
+some addresses to try to auto-detect it. That means that you will have to
+statically declare the device in the platform support code.
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp
index f17256f069ba..3374c085678d 100644
--- a/Documentation/hwmon/coretemp
+++ b/Documentation/hwmon/coretemp
@@ -98,8 +98,10 @@ Process Processor TjMax(C)
45nm Atom Processors
D525/510/425/410 100
+ Z670/650 90
Z560/550/540/530P/530/520PT/520/515/510PT/510P 90
Z510/500 90
+ N570/550 100
N475/470/455/450 100
N280/270 90
330/230 125
diff --git a/Documentation/hwmon/da9055 b/Documentation/hwmon/da9055
new file mode 100644
index 000000000000..855c3f536e00
--- /dev/null
+++ b/Documentation/hwmon/da9055
@@ -0,0 +1,47 @@
+Supported chips:
+ * Dialog Semiconductors DA9055 PMIC
+ Prefix: 'da9055'
+ Datasheet: Datasheet is not publicly available.
+
+Authors: David Dajun Chen <dchen@diasemi.com>
+
+Description
+-----------
+
+The DA9055 provides an Analogue to Digital Converter (ADC) with 10 bits
+resolution and track and hold circuitry combined with an analogue input
+multiplexer. The analogue input multiplexer will allow conversion of up to 5
+different inputs. The track and hold circuit ensures stable input voltages at
+the input of the ADC during the conversion.
+
+The ADC is used to measure the following inputs:
+Channel 0: VDDOUT - measurement of the system voltage
+Channel 1: ADC_IN1 - high impedance input (0 - 2.5V)
+Channel 2: ADC_IN2 - high impedance input (0 - 2.5V)
+Channel 3: ADC_IN3 - high impedance input (0 - 2.5V)
+Channel 4: Internal Tjunc. - sense (internal temp. sensor)
+
+By using sysfs attributes we can measure the system voltage VDDOUT,
+chip junction temperature and auxiliary channels voltages.
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled in a AUTO mode it can be manually sampled too and results
+are stored in a 10 bit ADC.
+
+The system voltage is calculated as:
+ Milli volt = ((ADC value * 1000) / 85) + 2500
+
+The voltages on ADC channels 1, 2 and 3 are calculated as:
+ Milli volt = (ADC value * 1000) / 102
+
+Temperature Monitoring
+----------------------
+
+Temperatures are sampled by a 10 bit ADC. Junction temperatures
+are monitored by the ADC channels.
+
+The junction temperature is calculated:
+ Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+The junction temperature attribute is supported by the driver.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index ec9ae6708691..14c3f4f1b617 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1175,15 +1175,16 @@ When kbuild executes, the following steps are followed (roughly):
in an init section in the image. Platform code *must* copy the
blob to non-init memory prior to calling unflatten_device_tree().
- Example:
- #arch/x86/platform/ce4100/Makefile
- clean-files := *dtb.S
+ To use this command, simply add *.dtb into obj-y or targets, or make
+ some other target depend on %.dtb
- DTC_FLAGS := -p 1024
- obj-y += foo.dtb.o
+ A central rule exists to create $(obj)/%.dtb from $(src)/%.dts;
+ architecture Makefiles do no need to explicitly write out that rule.
- $(obj)/%.dtb: $(src)/%.dts
- $(call cmd,dtc)
+ Example:
+ targets += $(dtb-y)
+ clean-files += *.dtb
+ DTC_FLAGS ?= -p 1024
--- 6.8 Custom kbuild commands
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 22ae8441489f..0d98fac8893b 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,6 +25,8 @@ All attributes are read-only.
serial Product Serial Number (from CID Register)
erase_size Erase group size
preferred_erase_size Preferred erase size
+ raw_rpmb_size_mult RPMB partition size
+ rel_sectors Reliable write sector count
Note on Erase Size and Preferred Erase Size:
@@ -65,6 +67,11 @@ Note on Erase Size and Preferred Erase Size:
"preferred_erase_size" is in bytes.
+Note on raw_rpmb_size_mult:
+ "raw_rpmb_size_mult" is a mutliple of 128kB block.
+ RPMB size in byte is calculated by using the following equation:
+ RPMB partition size = 128kB x raw_rpmb_size_mult
+
SD/MMC/SDIO Clock Gating Attribute
==================================
diff --git a/Documentation/networking/vxlan.txt b/Documentation/networking/vxlan.txt
index 5b34b762d7d5..6d993510f091 100644
--- a/Documentation/networking/vxlan.txt
+++ b/Documentation/networking/vxlan.txt
@@ -32,7 +32,7 @@ no entry is in the forwarding table.
# ip link delete vxlan0
3. Show vxlan info
- # ip -d show vxlan0
+ # ip -d link show vxlan0
It is possible to create, destroy and display the vxlan
forwarding table using the new bridge command.
@@ -41,7 +41,7 @@ forwarding table using the new bridge command.
# bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
2. Delete forwarding table entry
- # bridge fdb delete 00:17:42:8a:b4:05
+ # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
3. Show forwarding table
# bridge fdb show dev vxlan0
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 3b4ee5328868..da40efbef6ec 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
the range ID value, so that the pin controller knows which range it should
deal with.
+Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
+section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
+pinctrl and gpio drivers.
PINMUX interfaces
=================
@@ -1193,4 +1196,6 @@ foo_switch()
...
}
-The above has to be done from process context.
+The above has to be done from process context. The reservation of the pins
+will be done when the state is activated, so in effect one specific pin
+can be used by different functions at different times on a running system.
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index 17e130a80347..79a2a58425ee 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -99,7 +99,7 @@ reading the aggregated value does not require any locking mechanism.
From kernel mode the use of this interface is the following:
-int dev_pm_qos_add_request(device, handle, value):
+int dev_pm_qos_add_request(device, handle, type, value):
Will insert an element into the list for that identified device with the
target value. Upon change to this list the new target is recomputed and any
registered notifiers are called only if the target value is now different.
diff --git a/Documentation/zh_CN/arm/kernel_user_helpers.txt b/Documentation/zh_CN/arm/kernel_user_helpers.txt
new file mode 100644
index 000000000000..cd7fc8f34cf9
--- /dev/null
+++ b/Documentation/zh_CN/arm/kernel_user_helpers.txt
@@ -0,0 +1,284 @@
+Chinese translated version of Documentation/arm/kernel_user_helpers.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly. However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help. Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
+ Dave Martin <dave.martin@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm/kernel_user_helpers.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+英文版维护者: Nicolas Pitre <nicolas.pitre@linaro.org>
+ Dave Martin <dave.martin@linaro.org>
+中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
+ 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+内核提供的用户空间辅助代码
+=========================
+
+在内核内存空间的固定地址处,有一个由内核提供并可从用户空间访问的代码
+段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需
+内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得
+最佳效率,但那些与内核计数器联系过于紧密的部分,则被留给了用户库实现。
+事实上,此代码甚至可能因不同的 CPU 而异,这取决于其可用的指令集或它
+是否为 SMP 系统。换句话说,内核保留在不作出警告的情况下根据需要更改
+这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。
+
+这与完全成熟的 VDSO 实现不同(但两者并不冲突),尽管如此,VDSO 可阻止
+某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户
+代码前仅使用少量的代码周期,则一个 VDSO 间接远程调用将会在这些简单的
+操作上增加一个可测量的开销。
+
+在对那些拥有原生支持的新型处理器进行代码优化时,仅在已为其他操作使用
+了类似的新增指令,而导致二进制结果已与早期 ARM 处理器不兼容的情况下,
+用户空间才应绕过这些辅助代码,并在内联函数中实现这些操作(无论是通过
+编译器在代码中直接放置,还是作为库函数调用实现的一部分)。也就是说,
+如果你编译的代码不会为了其他目的使用新指令,则不要仅为了避免使用这些
+内核辅助代码,导致二进制程序无法在早期处理器上运行。
+
+新的辅助代码可能随着时间的推移而增加,所以新内核中的某些辅助代码在旧
+内核中可能不存在。因此,程序必须在对任何辅助代码调用假设是安全之前,
+检测 __kuser_helper_version 的值(见下文)。理想情况下,这种检测应该
+只在进程启动时执行一次;如果内核版本不支持所需辅助代码,则该进程可尽早
+中止执行。
+
+kuser_helper_version
+--------------------
+
+位置: 0xffff0ffc
+
+参考声明:
+
+ extern int32_t __kuser_helper_version;
+
+定义:
+
+ 这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读
+ 取此版本号以确定特定的辅助代码是否存在。
+
+使用范例:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+ if (__kuser_helper_version < 2) {
+ fprintf(stderr, "can't do atomic operations, kernel too old\n");
+ abort();
+ }
+}
+
+注意:
+
+ 用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就
+ 是说,这个域可以仅在库的初始化阶段或进程启动阶段读取一次。
+
+kuser_get_tls
+-------------
+
+位置: 0xffff0fe0
+
+参考原型:
+
+ void * __kuser_get_tls(void);
+
+输入:
+
+ lr = 返回地址
+
+输出:
+
+ r0 = TLS 值
+
+被篡改的寄存器:
+
+ 无
+
+定义:
+
+ 获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。
+
+使用范例:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+ void *tls = __kuser_get_tls();
+ printf("TLS = %p\n", tls);
+}
+
+注意:
+
+ - 仅在 __kuser_helper_version >= 1 时,此辅助代码存在
+ (从内核版本 2.6.12 开始)。
+
+kuser_cmpxchg
+-------------
+
+位置: 0xffff0fc0
+
+参考原型:
+
+ int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+输入:
+
+ r0 = oldval
+ r1 = newval
+ r2 = ptr
+ lr = 返回地址
+
+输出:
+
+ r0 = 成功代码 (零或非零)
+ C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+ r3, ip, flags
+
+定义:
+
+ 仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。
+ 如果 *ptr 被改变,则返回值为零,否则为非零值。
+ 如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编
+ 优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+ int old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg(old, new, ptr));
+
+ return new;
+}
+
+注意:
+
+ - 这个例程已根据需要包含了内存屏障。
+
+ - 仅在 __kuser_helper_version >= 2 时,此辅助代码存在
+ (从内核版本 2.6.12 开始)。
+
+kuser_memory_barrier
+--------------------
+
+位置: 0xffff0fa0
+
+参考原型:
+
+ void __kuser_memory_barrier(void);
+
+输入:
+
+ lr = 返回地址
+
+输出:
+
+ 无
+
+被篡改的寄存器:
+
+ 无
+
+定义:
+
+ 应用于任何需要内存屏障以防止手动数据修改带来的一致性问题,以及
+ __kuser_cmpxchg 中。
+
+使用范例:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+注意:
+
+ - 仅在 __kuser_helper_version >= 3 时,此辅助代码存在
+ (从内核版本 2.6.15 开始)。
+
+kuser_cmpxchg64
+---------------
+
+位置: 0xffff0f60
+
+参考原型:
+
+ int __kuser_cmpxchg64(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+
+输入:
+
+ r0 = 指向 oldval
+ r1 = 指向 newval
+ r2 = 指向目标值
+ lr = 返回地址
+
+输出:
+
+ r0 = 成功代码 (零或非零)
+ C flag = 如果 r0 == 0 则置 1,如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+ r3, lr, flags
+
+定义:
+
+ 仅在 *ptr 等于 *oldval 指向的 64 位值时,原子保存 *newval
+ 指向的 64 位值于 *ptr 中。如果 *ptr 被改变,则返回值为零,
+ 否则为非零值。
+
+ 如果 *ptr 被改变,则 C flag 也会被置 1,以实现调用代码中的汇编
+ 优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+ int64_t old, new;
+
+ do {
+ old = *ptr;
+ new = old + val;
+ } while(__kuser_cmpxchg64(&old, &new, ptr));
+
+ return new;
+}
+
+注意:
+
+ - 这个例程已根据需要包含了内存屏障。
+
+ - 由于这个过程的代码长度(此辅助代码跨越 2 个常规的 kuser “槽”),
+ 因此 0xffff0f80 不被作为有效的入口点。
+
+ - 仅在 __kuser_helper_version >= 5 时,此辅助代码存在
+ (从内核版本 3.1 开始)。
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
index 83b519314706..a5f6283829f9 100644
--- a/Documentation/zh_CN/arm64/memory.txt
+++ b/Documentation/zh_CN/arm64/memory.txt
@@ -47,21 +47,21 @@ AArch64 Linux 内存布局:
-----------------------------------------------------------------------
0000000000000000 0000007fffffffff 512GB 用户空间
-ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc
+ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
-ffffffbbfffd0000 ffffffbcfffdffff 64KB [防护页]
+ffffffbbffff0000 ffffffbbffffffff 64KB [防护页]
-ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O 空间
+ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
-ffffffbbffff0000 ffffffbcffffffff 64KB [防护页]
+ffffffbe00000000 ffffffbffbbfffff ~8GB [防护页,未来用于 vmmemap]
-ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
+ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O 空间
-ffffffbe00000000 ffffffbffbffffff ~8GB [防护页,未来用于 vmmemap]
+ffffffbbffff0000 ffffffbcffffffff ~2MB [防护页]
ffffffbffc000000 ffffffbfffffffff 64MB 模块
-ffffffc000000000 ffffffffffffffff 256GB 内存空间
+ffffffc000000000 ffffffffffffffff 256GB 内核逻辑内存映射
4KB 页大小的转换表查找:
diff --git a/MAINTAINERS b/MAINTAINERS
index adbdac1d43c5..1ea0eba7ee22 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -526,17 +526,17 @@ F: drivers/video/geode/
F: arch/x86/include/asm/geode.h
AMD IOMMU (AMD-VI)
-M: Joerg Roedel <joerg.roedel@amd.com>
+M: Joerg Roedel <joro@8bytes.org>
L: iommu@lists.linux-foundation.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-S: Supported
+S: Maintained
F: drivers/iommu/amd_iommu*.[ch]
F: include/linux/amd-iommu.h
AMD MICROCODE UPDATE SUPPORT
-M: Andreas Herrmann <andreas.herrmann3@amd.com>
+M: Andreas Herrmann <herrmann.der.user@googlemail.com>
L: amd64-microcode@amd64.org
-S: Supported
+S: Maintained
F: arch/x86/kernel/microcode_amd.c
AMS (Apple Motion Sensor) DRIVER
@@ -841,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
F: arch/arm/mach-sa1100/jornada720.c
F: arch/arm/mach-sa1100/include/mach/jornada720.h
+ARM/IGEP MACHINE SUPPORT
+M: Enric Balletbo i Serra <eballetbo@gmail.com>
+M: Javier Martinez Canillas <javier@dowhile0.org>
+L: linux-omap@vger.kernel.org
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-omap2/board-igep0020.c
+
ARM/INCOME PXA270 SUPPORT
M: Marek Vasut <marek.vasut@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1229,6 +1237,7 @@ F: drivers/video/wm8505fb*
F: drivers/video/wmt_ge_rops.*
F: drivers/tty/serial/vt8500_serial.c
F: drivers/rtc/rtc-vt8500-c
+F: drivers/mmc/host/wmt-sdmmc.c
ARM/ZIPIT Z2 SUPPORT
M: Marek Vasut <marek.vasut@gmail.com>
@@ -1360,14 +1369,6 @@ S: Maintained
F: drivers/atm/
F: include/linux/atm*
-ATMEL AT91 MCI DRIVER
-M: Ludovic Desroches <ludovic.desroches@atmel.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W: http://www.atmel.com/products/AT91/
-W: http://www.at91.com/
-S: Maintained
-F: drivers/mmc/host/at91_mci.c
-
ATMEL AT91 / AT32 MCI DRIVER
M: Ludovic Desroches <ludovic.desroches@atmel.com>
S: Maintained
@@ -1986,7 +1987,6 @@ F: fs/coda/
F: include/linux/coda*.h
COMMON CLK FRAMEWORK
-M: Mike Turquette <mturquette@ti.com>
M: Mike Turquette <mturquette@linaro.org>
L: linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV)
T: git git://git.linaro.org/people/mturquette/linux.git
@@ -2708,10 +2708,10 @@ F: include/linux/edac.h
EDAC-AMD64
M: Doug Thompson <dougthompson@xmission.com>
-M: Borislav Petkov <borislav.petkov@amd.com>
+M: Borislav Petkov <bp@alien8.de>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
-S: Supported
+S: Maintained
F: drivers/edac/amd64_edac*
EDAC-E752X
@@ -3596,7 +3596,6 @@ S: Maintained
F: drivers/hv/
F: drivers/hid/hid-hyperv.c
F: drivers/net/hyperv/
-F: drivers/staging/hv/
I2C OVER PARALLEL PORT
M: Jean Delvare <khali@linux-fr.org>
@@ -3753,7 +3752,7 @@ S: Maintained
F: drivers/platform/x86/ideapad-laptop.c
IDE/ATAPI DRIVERS
-M: Borislav Petkov <petkovbb@gmail.com>
+M: Borislav Petkov <bp@alien8.de>
L: linux-ide@vger.kernel.org
S: Maintained
F: Documentation/cdrom/ide-cd
@@ -4289,8 +4288,8 @@ F: include/linux/lockd/
F: include/linux/sunrpc/
KERNEL VIRTUAL MACHINE (KVM)
-M: Avi Kivity <avi@redhat.com>
M: Marcelo Tosatti <mtosatti@redhat.com>
+M: Gleb Natapov <gleb@redhat.com>
L: kvm@vger.kernel.org
W: http://kvm.qumranet.com
S: Supported
@@ -5422,7 +5421,7 @@ S: Maintained
F: sound/drivers/opl4/
OPROFILE
-M: Robert Richter <robert.richter@amd.com>
+M: Robert Richter <rric@kernel.org>
L: oprofile-list@lists.sf.net
S: Maintained
F: arch/*/include/asm/oprofile*.h
@@ -5697,6 +5696,12 @@ S: Maintained
F: drivers/pinctrl/
F: include/linux/pinctrl/
+PIN CONTROLLER - ATMEL AT91
+M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/pinctrl/pinctrl-at91.c
+
PIN CONTROLLER - ST SPEAR
M: Viresh Kumar <viresh.linux@gmail.com>
L: spear-devel@list.st.com
@@ -8207,7 +8212,7 @@ F: drivers/platform/x86
X86 MCE INFRASTRUCTURE
M: Tony Luck <tony.luck@intel.com>
-M: Borislav Petkov <bp@amd64.org>
+M: Borislav Petkov <bp@alien8.de>
L: linux-edac@vger.kernel.org
S: Maintained
F: arch/x86/kernel/cpu/mcheck/*
diff --git a/Makefile b/Makefile
index 9f6ca124e890..540f7b240c77 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 7
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
NAME = Terrified Chipmunk
# *DOCUMENTATION*
@@ -1321,10 +1321,12 @@ kernelversion:
# Clear a bunch of variables before executing the submake
tools/: FORCE
- $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/
tools/%: FORCE
- $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+ $(Q)mkdir -p $(objtree)/tools
+ $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*
# Single targets
# ---------------------------------------------------------------------------
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 1e6956a90608..14db93e4c8a8 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -445,7 +445,7 @@ struct procfs_args {
* unhappy with OSF UFS. [CHECKME]
*/
static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
}
static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
}
static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
{
struct procfs_args tmp;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ade7e924bef5..8a027f9e339e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -330,6 +330,8 @@ config ARCH_AT91
select IRQ_DOMAIN
select NEED_MACH_GPIO_H
select NEED_MACH_IO_H if PCCARD
+ select PINCTRL
+ select PINCTRL_AT91 if USE_OF
help
This enables support for systems based on Atmel
AT91RM9200 and AT91SAM9* processors.
@@ -364,6 +366,7 @@ config ARCH_CNS3XXX
config ARCH_CLPS711X
bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
+ select ARCH_REQUIRE_GPIOLIB
select ARCH_USES_GETTIMEOFFSET
select CLKDEV_LOOKUP
select COMMON_CLK
@@ -547,6 +550,7 @@ config ARCH_KIRKWOOD
select CPU_FEROCEON
select GENERIC_CLOCKEVENTS
select PCI
+ select PCI_QUIRKS
select PLAT_ORION_LEGACY
help
Support for the following Marvell Kirkwood series SoCs:
@@ -586,6 +590,7 @@ config ARCH_MMP
select GPIO_PXA
select IRQ_DOMAIN
select NEED_MACH_GPIO_H
+ select PINCTRL
select PLAT_PXA
select SPARSE_IRQ
help
@@ -904,6 +909,7 @@ config ARCH_NOMADIK
config PLAT_SPEAR
bool "ST SPEAr"
+ select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select ARM_AMBA
select CLKDEV_LOOKUP
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5f914fca911b..c35baf102f6f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -292,10 +292,10 @@ zinstall uinstall install: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
%.dtb: scripts
- $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
dtbs: scripts
- $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+ $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
# We use MRPROPER_FILES and CLEAN_FILES now
archclean:
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 9137df539b61..abfce280f57b 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -15,8 +15,6 @@ ifneq ($(MACHINE),)
include $(srctree)/$(MACHINE)/Makefile.boot
endif
-include $(srctree)/arch/arm/boot/dts/Makefile
-
# Note: the following conditions must always be true:
# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
# PARAMS_PHYS must be within 4MB of ZRELADDR
@@ -59,16 +57,6 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
endif
-targets += $(dtb-y)
-
-# Rule to build device tree blobs
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
- $(call if_changed_dep,dtc)
-
-$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
-
-clean-files := *.dtb
-
ifneq ($(LOADADDR),)
UIMAGE_LOADADDR=$(LOADADDR)
else
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 90275f036cd1..49ca86e37b8d 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -652,6 +652,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
mov pc, lr
ENDPROC(__setup_mmu)
+@ Enable unaligned access on v6, to allow better code generation
+@ for the decompressor C code:
+__armv6_mmu_cache_on:
+ mrc p15, 0, r0, c1, c0, 0 @ read SCTLR
+ bic r0, r0, #2 @ A (no unaligned access fault)
+ orr r0, r0, #1 << 22 @ U (v6 unaligned access model)
+ mcr p15, 0, r0, c1, c0, 0 @ write SCTLR
+ b __armv4_mmu_cache_on
+
__arm926ejs_mmu_cache_on:
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
mov r0, #4 @ put dcache in WT mode
@@ -694,6 +703,9 @@ __armv7_mmu_cache_on:
bic r0, r0, #1 << 28 @ clear SCTLR.TRE
orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
orr r0, r0, #0x003c @ write buffer
+ bic r0, r0, #2 @ A (no unaligned access fault)
+ orr r0, r0, #1 << 22 @ U (v6 unaligned access model)
+ @ (needed for ARM1176)
#ifdef CONFIG_MMU
#ifdef CONFIG_CPU_ENDIAN_BE8
orr r0, r0, #1 << 25 @ big-endian page tables
@@ -914,7 +926,7 @@ proc_types:
.word 0x0007b000 @ ARMv6
.word 0x000ff000
- W(b) __armv4_mmu_cache_on
+ W(b) __armv6_mmu_cache_on
W(b) __armv4_mmu_cache_off
W(b) __armv6_mmu_cache_flush
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index f37cf9fa5fa0..262493752234 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1,21 +1,37 @@
ifeq ($(CONFIG_OF),y)
-dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \
- at91sam9263ek.dtb \
- at91sam9g20ek_2mmc.dtb \
- at91sam9g20ek.dtb \
- at91sam9g25ek.dtb \
- at91sam9m10g45ek.dtb \
- at91sam9n12ek.dtb \
- ethernut5.dtb \
- evk-pro3.dtb \
- kizbox.dtb \
- tny_a9260.dtb \
- tny_a9263.dtb \
- tny_a9g20.dtb \
- usb_a9260.dtb \
- usb_a9263.dtb \
- usb_a9g20.dtb
+# Keep at91 dtb files sorted alphabetically for each SoC
+# rm9200
+dtb-$(CONFIG_ARCH_AT91) += at91rm9200ek.dtb
+# sam9260
+dtb-$(CONFIG_ARCH_AT91) += animeo_ip.dtb
+dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb
+dtb-$(CONFIG_ARCH_AT91) += ethernut5.dtb
+dtb-$(CONFIG_ARCH_AT91) += evk-pro3.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9260.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9260.dtb
+# sam9263
+dtb-$(CONFIG_ARCH_AT91) += at91sam9263ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9263.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9263.dtb
+# sam9g20
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g20ek_2mmc.dtb
+dtb-$(CONFIG_ARCH_AT91) += kizbox.dtb
+dtb-$(CONFIG_ARCH_AT91) += tny_a9g20.dtb
+dtb-$(CONFIG_ARCH_AT91) += usb_a9g20.dtb
+# sam9g45
+dtb-$(CONFIG_ARCH_AT91) += at91sam9m10g45ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += pm9g45.dtb
+# sam9n12
+dtb-$(CONFIG_ARCH_AT91) += at91sam9n12ek.dtb
+# sam9x5
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g15ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x25ek.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91sam9x35ek.dtb
+
dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
dove-cubox.dtb \
@@ -104,4 +120,12 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
wm8505-ref.dtb \
wm8650-mid.dtb
+targets += dtbs
endif
+
+# *.dtb used to be generated in the directory above. Clean out the
+# old build results so people don't accidentally use them.
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+ $(Q)rm -f $(obj)/../*.dtb
+
+clean-files := *.dtb
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
new file mode 100644
index 000000000000..74d92cd29d87
--- /dev/null
+++ b/arch/arm/boot/dts/animeo_ip.dts
@@ -0,0 +1,178 @@
+/*
+ * animeo_ip.dts - Device Tree file for Somfy Animeo IP Boards
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only.
+ */
+
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+
+/ {
+ model = "Somfy Animeo IP";
+ compatible = "somfy,animeo-ip", "atmel,at91sam9260", "atmel,at91sam9";
+
+ aliases {
+ serial0 = &usart1;
+ serial1 = &usart2;
+ serial2 = &usart0;
+ serial3 = &dbgu;
+ serial4 = &usart3;
+ serial5 = &uart0;
+ serial6 = &uart1;
+ };
+
+ chosen {
+ linux,stdout-path = &usart2;
+ };
+
+ 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 {
+ usart0: serial@fffb0000 {
+ pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts>;
+ linux,rs485-enabled-at-boot-time;
+ status = "okay";
+ };
+
+ usart1: serial@fffb4000 {
+ pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts>;
+ linux,rs485-enabled-at-boot-time;
+ status = "okay";
+ };
+
+ usart2: serial@fffb8000 {
+ pinctrl-0 = <&pinctrl_usart2>;
+ status = "okay";
+ };
+
+ macb0: ethernet@fffc4000 {
+ pinctrl-0 = <&pinctrl_macb_rmii &pinctrl_macb_rmii_mii>;
+ phy-mode = "mii";
+ status = "okay";
+ };
+
+ mmc0: mmc@fffa8000 {
+ pinctrl-0 = <&pinctrl_mmc0_clk
+ &pinctrl_mmc0_slot1_cmd_dat0
+ &pinctrl_mmc0_slot1_dat1_3>;
+ status = "okay";
+
+ slot@1 {
+ reg = <1>;
+ bus-width = <4>;
+ };
+ };
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x8000>;
+ };
+
+ barebox@8000 {
+ label = "barebox";
+ reg = <0x8000 0x40000>;
+ };
+
+ bareboxenv@48000 {
+ label = "bareboxenv";
+ reg = <0x48000 0x8000>;
+ };
+
+ user_block@0x50000 {
+ label = "user_block";
+ reg = <0x50000 0xb0000>;
+ };
+
+ kernel@100000 {
+ label = "kernel";
+ reg = <0x100000 0x1b0000>;
+ };
+
+ root@2b0000 {
+ label = "root";
+ reg = <0x2b0000 0x1D50000>;
+ };
+ };
+
+ usb0: ohci@00500000 {
+ num-ports = <2>;
+ atmel,vbus-gpio = <&pioB 15 1>;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ power_green {
+ label = "power_green";
+ gpios = <&pioC 17 0>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ power_red {
+ label = "power_red";
+ gpios = <&pioA 2 0>;
+ };
+
+ tx_green {
+ label = "tx_green";
+ gpios = <&pioC 19 0>;
+ };
+
+ tx_red {
+ label = "tx_red";
+ gpios = <&pioC 18 0>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ keyswitch_in {
+ label = "keyswitch_in";
+ gpios = <&pioB 1 0>;
+ linux,code = <28>;
+ gpio-key,wakeup;
+ };
+
+ error_in {
+ label = "error_in";
+ gpios = <&pioB 2 0>;
+ linux,code = <29>;
+ gpio-key,wakeup;
+ };
+
+ btn {
+ label = "btn";
+ gpios = <&pioC 23 0>;
+ linux,code = <31>;
+ gpio-key,wakeup;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
new file mode 100644
index 000000000000..e154f242c680
--- /dev/null
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -0,0 +1,349 @@
+/*
+ * at91rm9200.dtsi - Device Tree Include file for AT91RM9200 family SoC
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ * 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on at91sam9260.dtsi
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Atmel AT91RM9200 family SoC";
+ compatible = "atmel,at91rm9200";
+ 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,arm920t";
+ };
+ };
+
+ 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 = <3>;
+ compatible = "atmel,at91rm9200-aic";
+ interrupt-controller;
+ reg = <0xfffff000 0x200>;
+ atmel,external-irqs = <25 26 27 28 29 30 31>;
+ };
+
+ ramc0: ramc@ffffff00 {
+ compatible = "atmel,at91rm9200-sdramc";
+ reg = <0xffffff00 0x100>;
+ };
+
+ pmc: pmc@fffffc00 {
+ compatible = "atmel,at91rm9200-pmc";
+ reg = <0xfffffc00 0x100>;
+ };
+
+ st: timer@fffffd00 {
+ compatible = "atmel,at91rm9200-st";
+ reg = <0xfffffd00 0x100>;
+ interrupts = <1 4 7>;
+ };
+
+ tcb0: timer@fffa0000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffa0000 0x100>;
+ interrupts = <17 4 0 18 4 0 19 4 0>;
+ };
+
+ tcb1: timer@fffa4000 {
+ compatible = "atmel,at91rm9200-tcb";
+ reg = <0xfffa4000 0x100>;
+ interrupts = <20 4 0 21 4 0 22 4 0>;
+ };
+
+ pinctrl@fffff400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff400 0xfffff400 0x800>;
+
+ atmel,mux-mask = <
+ /* A B */
+ 0xffffffff 0xffffffff /* pioA */
+ 0xffffffff 0x083fffff /* pioB */
+ 0xffff3fff 0x00000000 /* pioC */
+ 0x03ff87ff 0x0fffff80 /* pioD */
+ >;
+
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <0 30 0x1 0x0 /* PA30 periph A */
+ 0 31 0x1 0x1>; /* PA31 periph with pullup */
+ };
+ };
+
+ uart0 {
+ pinctrl_uart0: uart0-0 {
+ atmel,pins =
+ <0 17 0x1 0x0 /* PA17 periph A */
+ 0 18 0x1 0x0>; /* PA18 periph A */
+ };
+
+ pinctrl_uart0_rts: uart0_rts-0 {
+ atmel,pins =
+ <0 20 0x1 0x0>; /* PA20 periph A */
+ };
+
+ pinctrl_uart0_cts: uart0_cts-0 {
+ atmel,pins =
+ <0 21 0x1 0x0>; /* PA21 periph A */
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1: uart1-0 {
+ atmel,pins =
+ <1 20 0x1 0x1 /* PB20 periph A with pullup */
+ 1 21 0x1 0x0>; /* PB21 periph A */
+ };
+
+ pinctrl_uart1_rts: uart1_rts-0 {
+ atmel,pins =
+ <1 24 0x1 0x0>; /* PB24 periph A */
+ };
+
+ pinctrl_uart1_cts: uart1_cts-0 {
+ atmel,pins =
+ <1 26 0x1 0x0>; /* PB26 periph A */
+ };
+
+ pinctrl_uart1_dtr_dsr: uart1_dtr_dsr-0 {
+ atmel,pins =
+ <1 19 0x1 0x0 /* PB19 periph A */
+ 1 25 0x1 0x0>; /* PB25 periph A */
+ };
+
+ pinctrl_uart1_dcd: uart1_dcd-0 {
+ atmel,pins =
+ <1 23 0x1 0x0>; /* PB23 periph A */
+ };
+
+ pinctrl_uart1_ri: uart1_ri-0 {
+ atmel,pins =
+ <1 18 0x1 0x0>; /* PB18 periph A */
+ };
+ };
+
+ uart2 {
+ pinctrl_uart2: uart2-0 {
+ atmel,pins =
+ <0 22 0x1 0x0 /* PA22 periph A */
+ 0 23 0x1 0x1>; /* PA23 periph A with pullup */
+ };
+
+ pinctrl_uart2_rts: uart2_rts-0 {
+ atmel,pins =
+ <0 30 0x2 0x0>; /* PA30 periph B */
+ };
+
+ pinctrl_uart2_cts: uart2_cts-0 {
+ atmel,pins =
+ <0 31 0x2 0x0>; /* PA31 periph B */
+ };
+ };
+
+ uart3 {
+ pinctrl_uart3: uart3-0 {
+ atmel,pins =
+ <0 5 0x2 0x1 /* PA5 periph B with pullup */
+ 0 6 0x2 0x0>; /* PA6 periph B */
+ };
+
+ pinctrl_uart3_rts: uart3_rts-0 {
+ atmel,pins =
+ <1 0 0x2 0x0>; /* PB0 periph B */
+ };
+
+ pinctrl_uart3_cts: uart3_cts-0 {
+ atmel,pins =
+ <1 1 0x2 0x0>; /* PB1 periph B */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <2 2 0x0 0x1 /* PC2 gpio RDY pin pull_up */
+ 1 1 0x0 0x1>; /* PB1 gpio CD pin pull_up */
+ };
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio@fffffa00 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <5 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ dbgu: serial@fffff200 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffff200 0x200>;
+ interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
+ status = "disabled";
+ };
+
+ usart0: serial@fffc0000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc0000 0x200>;
+ interrupts = <6 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart0>;
+ status = "disabled";
+ };
+
+ usart1: serial@fffc4000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc4000 0x200>;
+ interrupts = <7 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "disabled";
+ };
+
+ usart2: serial@fffc8000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffc8000 0x200>;
+ interrupts = <8 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "disabled";
+ };
+
+ usart3: serial@fffcc000 {
+ compatible = "atmel,at91rm9200-usart";
+ reg = <0xfffcc000 0x200>;
+ interrupts = <23 4 5>;
+ atmel,use-dma-rx;
+ atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "disabled";
+ };
+
+ usb1: gadget@fffb0000 {
+ compatible = "atmel,at91rm9200-udc";
+ reg = <0xfffb0000 0x4000>;
+ interrupts = <11 4 2>;
+ status = "disabled";
+ };
+ };
+
+ nand0: nand@40000000 {
+ compatible = "atmel,at91rm9200-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x40000000 0x10000000>;
+ atmel,nand-addr-offset = <21>;
+ atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
+ nand-ecc-mode = "soft";
+ gpios = <&pioC 2 0
+ 0
+ &pioB 1 0
+ >;
+ status = "disabled";
+ };
+
+ usb0: ohci@00300000 {
+ compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+ reg = <0x00300000 0x100000>;
+ interrupts = <23 4 2>;
+ 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/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts
new file mode 100644
index 000000000000..8aa48931e0a2
--- /dev/null
+++ b/arch/arm/boot/dts/at91rm9200ek.dts
@@ -0,0 +1,79 @@
+/*
+ * at91rm9200ek.dts - Device Tree file for Atmel AT91RM9200 evaluation kit
+ *
+ * Copyright (C) 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91rm9200.dtsi"
+
+/ {
+ model = "Atmel AT91RM9200 evaluation kit";
+ compatible = "atmel,at91rm9200ek", "atmel,at91rm9200";
+
+ 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";
+ };
+
+ usart1: serial@fffc4000 {
+ pinctrl-0 =
+ <&pinctrl_uart1
+ &pinctrl_uart1_rts
+ &pinctrl_uart1_cts
+ &pinctrl_uart1_dtr_dsr
+ &pinctrl_uart1_dcd
+ &pinctrl_uart1_ri>;
+ status = "okay";
+ };
+
+ usb1: gadget@fffb0000 {
+ atmel,vbus-gpio = <&pioD 4 0>;
+ status = "okay";
+ };
+ };
+
+ usb0: ohci@00300000 {
+ num-ports = <2>;
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ ds2 {
+ label = "green";
+ gpios = <&pioB 0 0x1>;
+ linux,default-trigger = "mmc0";
+ };
+
+ ds4 {
+ label = "yellow";
+ gpios = <&pioB 1 0x1>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ ds6 {
+ label = "red";
+ gpios = <&pioB 2 0x1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index d410581a5a85..b1d3fab60e0a 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -21,8 +21,8 @@
serial2 = &usart1;
serial3 = &usart2;
serial4 = &usart3;
- serial5 = &usart4;
- serial6 = &usart5;
+ serial5 = &uart0;
+ serial6 = &uart1;
gpio0 = &pioA;
gpio1 = &pioB;
gpio2 = &pioC;
@@ -98,40 +98,250 @@
interrupts = <26 4 0 27 4 0 28 4 0>;
};
- pioA: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pinctrl@fffff400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff400 0xfffff400 0x600>;
+
+ atmel,mux-mask = <
+ /* A B */
+ 0xffffffff 0xffc00c3b /* pioA */
+ 0xffffffff 0x7fff3ccf /* pioB */
+ 0xffffffff 0x007fffff /* pioC */
+ >;
+
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <1 14 0x1 0x0 /* PB14 periph A */
+ 1 15 0x1 0x1>; /* PB15 periph with pullup */
+ };
+ };
- pioB: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ usart0 {
+ pinctrl_usart0: usart0-0 {
+ atmel,pins =
+ <1 4 0x1 0x0 /* PB4 periph A */
+ 1 5 0x1 0x0>; /* PB5 periph A */
+ };
+
+ pinctrl_usart0_rts: usart0_rts-0 {
+ atmel,pins =
+ <1 26 0x1 0x0>; /* PB26 periph A */
+ };
+
+ pinctrl_usart0_cts: usart0_cts-0 {
+ atmel,pins =
+ <1 27 0x1 0x0>; /* PB27 periph A */
+ };
+
+ pinctrl_usart0_dtr_dsr: usart0_dtr_dsr-0 {
+ atmel,pins =
+ <1 24 0x1 0x0 /* PB24 periph A */
+ 1 22 0x1 0x0>; /* PB22 periph A */
+ };
+
+ pinctrl_usart0_dcd: usart0_dcd-0 {
+ atmel,pins =
+ <1 23 0x1 0x0>; /* PB23 periph A */
+ };
+
+ pinctrl_usart0_ri: usart0_ri-0 {
+ atmel,pins =
+ <1 25 0x1 0x0>; /* PB25 periph A */
+ };
+ };
- pioC: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ usart1 {
+ pinctrl_usart1: usart1-0 {
+ atmel,pins =
+ <2 6 0x1 0x1 /* PB6 periph A with pullup */
+ 2 7 0x1 0x0>; /* PB7 periph A */
+ };
+
+ pinctrl_usart1_rts: usart1_rts-0 {
+ atmel,pins =
+ <1 28 0x1 0x0>; /* PB28 periph A */
+ };
+
+ pinctrl_usart1_cts: usart1_cts-0 {
+ atmel,pins =
+ <1 29 0x1 0x0>; /* PB29 periph A */
+ };
+ };
+
+ usart2 {
+ pinctrl_usart2: usart2-0 {
+ atmel,pins =
+ <1 8 0x1 0x1 /* PB8 periph A with pullup */
+ 1 9 0x1 0x0>; /* PB9 periph A */
+ };
+
+ pinctrl_usart2_rts: usart2_rts-0 {
+ atmel,pins =
+ <0 4 0x1 0x0>; /* PA4 periph A */
+ };
+
+ pinctrl_usart2_cts: usart2_cts-0 {
+ atmel,pins =
+ <0 5 0x1 0x0>; /* PA5 periph A */
+ };
+ };
+
+ usart3 {
+ pinctrl_usart3: usart3-0 {
+ atmel,pins =
+ <2 10 0x1 0x1 /* PB10 periph A with pullup */
+ 2 11 0x1 0x0>; /* PB11 periph A */
+ };
+
+ pinctrl_usart3_rts: usart3_rts-0 {
+ atmel,pins =
+ <3 8 0x2 0x0>; /* PB8 periph B */
+ };
+
+ pinctrl_usart3_cts: usart3_cts-0 {
+ atmel,pins =
+ <3 10 0x2 0x0>; /* PB10 periph B */
+ };
+ };
+
+ uart0 {
+ pinctrl_uart0: uart0-0 {
+ atmel,pins =
+ <0 31 0x2 0x1 /* PA31 periph B with pullup */
+ 0 30 0x2 0x0>; /* PA30 periph B */
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1: uart1-0 {
+ atmel,pins =
+ <2 12 0x1 0x1 /* PB12 periph A with pullup */
+ 2 13 0x1 0x0>; /* PB13 periph A */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <2 13 0x0 0x1 /* PC13 gpio RDY pin pull_up */
+ 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+ };
+ };
+
+ macb {
+ pinctrl_macb_rmii: macb_rmii-0 {
+ atmel,pins =
+ <0 12 0x1 0x0 /* PA12 periph A */
+ 0 13 0x1 0x0 /* PA13 periph A */
+ 0 14 0x1 0x0 /* PA14 periph A */
+ 0 15 0x1 0x0 /* PA15 periph A */
+ 0 16 0x1 0x0 /* PA16 periph A */
+ 0 17 0x1 0x0 /* PA17 periph A */
+ 0 18 0x1 0x0 /* PA18 periph A */
+ 0 19 0x1 0x0 /* PA19 periph A */
+ 0 20 0x1 0x0 /* PA20 periph A */
+ 0 21 0x1 0x0>; /* PA21 periph A */
+ };
+
+ pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+ atmel,pins =
+ <0 22 0x2 0x0 /* PA22 periph B */
+ 0 23 0x2 0x0 /* PA23 periph B */
+ 0 24 0x2 0x0 /* PA24 periph B */
+ 0 25 0x2 0x0 /* PA25 periph B */
+ 0 26 0x2 0x0 /* PA26 periph B */
+ 0 27 0x2 0x0 /* PA27 periph B */
+ 0 28 0x2 0x0 /* PA28 periph B */
+ 0 29 0x2 0x0>; /* PA29 periph B */
+ };
+
+ pinctrl_macb_rmii_mii_alt: macb_rmii_mii-1 {
+ atmel,pins =
+ <0 10 0x2 0x0 /* PA10 periph B */
+ 0 11 0x2 0x0 /* PA11 periph B */
+ 0 24 0x2 0x0 /* PA24 periph B */
+ 0 25 0x2 0x0 /* PA25 periph B */
+ 0 26 0x2 0x0 /* PA26 periph B */
+ 0 27 0x2 0x0 /* PA27 periph B */
+ 0 28 0x2 0x0 /* PA28 periph B */
+ 0 29 0x2 0x0>; /* PA29 periph B */
+ };
+ };
+
+ mmc0 {
+ pinctrl_mmc0_clk: mmc0_clk-0 {
+ atmel,pins =
+ <0 8 0x1 0x0>; /* PA8 periph A */
+ };
+
+ pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+ atmel,pins =
+ <0 7 0x1 0x1 /* PA7 periph A with pullup */
+ 0 6 0x1 0x1>; /* PA6 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 9 0x1 0x1 /* PA9 periph A with pullup */
+ 0 10 0x1 0x1 /* PA10 periph A with pullup */
+ 0 11 0x1 0x1>; /* PA11 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+ atmel,pins =
+ <0 1 0x2 0x1 /* PA1 periph B with pullup */
+ 0 0 0x2 0x1>; /* PA0 periph B with pullup */
+ };
+
+ pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+ atmel,pins =
+ <0 5 0x2 0x1 /* PA5 periph B with pullup */
+ 0 4 0x2 0x1 /* PA4 periph B with pullup */
+ 0 3 0x2 0x1>; /* PA3 periph B with pullup */
+ };
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
dbgu: serial@fffff200 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfffff200 0x200>;
interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
status = "disabled";
};
@@ -141,6 +351,8 @@
interrupts = <6 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart0>;
status = "disabled";
};
@@ -150,6 +362,8 @@
interrupts = <7 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
status = "disabled";
};
@@ -159,6 +373,8 @@
interrupts = <8 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2>;
status = "disabled";
};
@@ -168,24 +384,30 @@
interrupts = <23 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart3>;
status = "disabled";
};
- usart4: serial@fffd4000 {
+ uart0: serial@fffd4000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfffd4000 0x200>;
interrupts = <24 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart0>;
status = "disabled";
};
- usart5: serial@fffd8000 {
+ uart1: serial@fffd8000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfffd8000 0x200>;
interrupts = <25 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
status = "disabled";
};
@@ -193,6 +415,8 @@
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xfffc4000 0x100>;
interrupts = <21 4 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb_rmii>;
status = "disabled";
};
@@ -212,6 +436,15 @@
status = "disabled";
};
+ mmc0: mmc@fffa8000 {
+ compatible = "atmel,hsmci";
+ reg = <0xfffa8000 0x600>;
+ interrupts = <9 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
adc0: adc@fffe0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffe0000 0x100>;
@@ -257,6 +490,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioC 13 0
&pioC 14 0
0
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 3e6e5c1abbf3..66106eecf1ed 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -89,60 +89,243 @@
reg = <0xfffffd10 0x10>;
};
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pinctrl@fffff200 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff200 0xfffff200 0xa00>;
- pioB: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ atmel,mux-mask = <
+ /* A B */
+ 0xfffffffb 0xffffe07f /* pioA */
+ 0x0007ffff 0x39072fff /* pioB */
+ 0xffffffff 0x3ffffff8 /* pioC */
+ 0xfffffbff 0xffffffff /* pioD */
+ 0xffe00fff 0xfbfcff00 /* pioE */
+ >;
- pioC: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <2 30 0x1 0x0 /* PC30 periph A */
+ 2 31 0x1 0x1>; /* PC31 periph with pullup */
+ };
+ };
- pioD: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ usart0 {
+ pinctrl_usart0: usart0-0 {
+ atmel,pins =
+ <0 26 0x1 0x1 /* PA26 periph A with pullup */
+ 0 27 0x1 0x0>; /* PA27 periph A */
+ };
- pioE: gpio@fffffa00 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
- interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ pinctrl_usart0_rts: usart0_rts-0 {
+ atmel,pins =
+ <0 28 0x1 0x0>; /* PA28 periph A */
+ };
+
+ pinctrl_usart0_cts: usart0_cts-0 {
+ atmel,pins =
+ <0 29 0x1 0x0>; /* PA29 periph A */
+ };
+ };
+
+ usart1 {
+ pinctrl_usart1: usart1-0 {
+ atmel,pins =
+ <3 0 0x1 0x1 /* PD0 periph A with pullup */
+ 3 1 0x1 0x0>; /* PD1 periph A */
+ };
+
+ pinctrl_usart1_rts: usart1_rts-0 {
+ atmel,pins =
+ <3 7 0x2 0x0>; /* PD7 periph B */
+ };
+
+ pinctrl_usart1_cts: usart1_cts-0 {
+ atmel,pins =
+ <3 8 0x2 0x0>; /* PD8 periph B */
+ };
+ };
+
+ usart2 {
+ pinctrl_usart2: usart2-0 {
+ atmel,pins =
+ <3 2 0x1 0x1 /* PD2 periph A with pullup */
+ 3 3 0x1 0x0>; /* PD3 periph A */
+ };
+
+ pinctrl_usart2_rts: usart2_rts-0 {
+ atmel,pins =
+ <3 5 0x2 0x0>; /* PD5 periph B */
+ };
+
+ pinctrl_usart2_cts: usart2_cts-0 {
+ atmel,pins =
+ <4 6 0x2 0x0>; /* PD6 periph B */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <0 22 0x0 0x1 /* PA22 gpio RDY pin pull_up*/
+ 3 15 0x0 0x1>; /* PD15 gpio enable pin pull_up */
+ };
+ };
+
+ macb {
+ pinctrl_macb_rmii: macb_rmii-0 {
+ atmel,pins =
+ <2 25 0x2 0x0 /* PC25 periph B */
+ 4 21 0x1 0x0 /* PE21 periph A */
+ 4 23 0x1 0x0 /* PE23 periph A */
+ 4 24 0x1 0x0 /* PE24 periph A */
+ 4 25 0x1 0x0 /* PE25 periph A */
+ 4 26 0x1 0x0 /* PE26 periph A */
+ 4 27 0x1 0x0 /* PE27 periph A */
+ 4 28 0x1 0x0 /* PE28 periph A */
+ 4 29 0x1 0x0 /* PE29 periph A */
+ 4 30 0x1 0x0>; /* PE30 periph A */
+ };
+
+ pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+ atmel,pins =
+ <2 20 0x2 0x0 /* PC20 periph B */
+ 2 21 0x2 0x0 /* PC21 periph B */
+ 2 22 0x2 0x0 /* PC22 periph B */
+ 2 23 0x2 0x0 /* PC23 periph B */
+ 2 24 0x2 0x0 /* PC24 periph B */
+ 2 25 0x2 0x0 /* PC25 periph B */
+ 2 27 0x2 0x0 /* PC27 periph B */
+ 4 22 0x2 0x0>; /* PE22 periph B */
+ };
+ };
+
+ mmc0 {
+ pinctrl_mmc0_clk: mmc0_clk-0 {
+ atmel,pins =
+ <0 12 0x1 0x0>; /* PA12 periph A */
+ };
+
+ pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+ atmel,pins =
+ <0 1 0x1 0x1 /* PA1 periph A with pullup */
+ 0 0 0x1 0x1>; /* PA0 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 3 0x1 0x1 /* PA3 periph A with pullup */
+ 0 4 0x1 0x1 /* PA4 periph A with pullup */
+ 0 5 0x1 0x1>; /* PA5 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+ atmel,pins =
+ <0 16 0x1 0x1 /* PA16 periph A with pullup */
+ 0 17 0x1 0x1>; /* PA17 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+ atmel,pins =
+ <0 18 0x1 0x1 /* PA18 periph A with pullup */
+ 0 19 0x1 0x1 /* PA19 periph A with pullup */
+ 0 20 0x1 0x1>; /* PA20 periph A with pullup */
+ };
+ };
+
+ mmc1 {
+ pinctrl_mmc1_clk: mmc1_clk-0 {
+ atmel,pins =
+ <0 6 0x1 0x0>; /* PA6 periph A */
+ };
+
+ pinctrl_mmc1_slot0_cmd_dat0: mmc1_slot0_cmd_dat0-0 {
+ atmel,pins =
+ <0 7 0x1 0x1 /* PA7 periph A with pullup */
+ 0 8 0x1 0x1>; /* PA8 periph A with pullup */
+ };
+
+ pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 9 0x1 0x1 /* PA9 periph A with pullup */
+ 0 10 0x1 0x1 /* PA10 periph A with pullup */
+ 0 11 0x1 0x1>; /* PA11 periph A with pullup */
+ };
+
+ pinctrl_mmc1_slot1_cmd_dat0: mmc1_slot1_cmd_dat0-0 {
+ atmel,pins =
+ <0 21 0x1 0x1 /* PA21 periph A with pullup */
+ 0 22 0x1 0x1>; /* PA22 periph A with pullup */
+ };
+
+ pinctrl_mmc1_slot1_dat1_3: mmc1_slot1_dat1_3-0 {
+ atmel,pins =
+ <0 23 0x1 0x1 /* PA23 periph A with pullup */
+ 0 24 0x1 0x1 /* PA24 periph A with pullup */
+ 0 25 0x1 0x1>; /* PA25 periph A with pullup */
+ };
+ };
+
+ pioA: gpio@fffff200 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff200 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioE: gpio@fffffa00 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
dbgu: serial@ffffee00 {
compatible = "atmel,at91sam9260-usart";
reg = <0xffffee00 0x200>;
interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
status = "disabled";
};
@@ -152,6 +335,8 @@
interrupts = <7 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart0>;
status = "disabled";
};
@@ -161,6 +346,8 @@
interrupts = <8 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
status = "disabled";
};
@@ -170,6 +357,8 @@
interrupts = <9 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2>;
status = "disabled";
};
@@ -177,6 +366,8 @@
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xfffbc000 0x100>;
interrupts = <21 4 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb_rmii>;
status = "disabled";
};
@@ -195,6 +386,24 @@
#size-cells = <0>;
status = "disabled";
};
+
+ mmc0: mmc@fff80000 {
+ compatible = "atmel,hsmci";
+ reg = <0xfff80000 0x600>;
+ interrupts = <10 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@fff84000 {
+ compatible = "atmel,hsmci";
+ reg = <0xfff84000 0x600>;
+ interrupts = <11 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
nand0: nand@40000000 {
@@ -206,6 +415,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioA 22 0
&pioD 15 0
0
diff --git a/arch/arm/boot/dts/at91sam9263ek.dts b/arch/arm/boot/dts/at91sam9263ek.dts
index f86ac4b609fc..1eb08728f527 100644
--- a/arch/arm/boot/dts/at91sam9263ek.dts
+++ b/arch/arm/boot/dts/at91sam9263ek.dts
@@ -38,6 +38,10 @@
};
usart0: serial@fff8c000 {
+ pinctrl-0 = <
+ &pinctrl_usart0
+ &pinctrl_usart0_rts
+ &pinctrl_usart0_cts>;
status = "okay";
};
@@ -50,6 +54,31 @@
atmel,vbus-gpio = <&pioA 25 0>;
status = "okay";
};
+
+ mmc0: mmc@fff80000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_clk
+ &pinctrl_mmc0_slot0_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioE 18 0>;
+ wp-gpios = <&pioE 19 0>;
+ };
+ };
+
+ pinctrl@fffff200 {
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <5 18 0x0 0x5 /* PE18 gpio CD pin pull up and deglitch */
+ 5 19 0x0 0x1>; /* PE19 gpio WP pin pull up */
+ };
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g15.dtsi b/arch/arm/boot/dts/at91sam9g15.dtsi
new file mode 100644
index 000000000000..fbe7a7089c2a
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g15.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g15.dtsi - Device Tree Include file for AT91SAM9G15 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G15 SoC";
+ compatible = "atmel, at91sam9g15, atmel,at91sam9x5";
+
+ ahb {
+ apb {
+ pinctrl@fffff400 {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe0399f 0x00000000 /* pioA */
+ 0x00040000 0x00047e3f 0x00000000 /* pioB */
+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g15ek.dts b/arch/arm/boot/dts/at91sam9g15ek.dts
new file mode 100644
index 000000000000..86dd3f6d938f
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g15ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g15ek.dts - Device Tree file for AT91SAM9G15-EK board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g15.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G25-EK";
+ compatible = "atmel,at91sam9g15ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
index f1b2e148ac8c..66467b113126 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
+++ b/arch/arm/boot/dts/at91sam9g20ek_2mmc.dts
@@ -12,6 +12,32 @@
model = "Atmel at91sam9g20ek 2 mmc";
compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
+ ahb {
+ apb{
+ mmc0: mmc@fffa8000 {
+ /* clk already mux wuth slot0 */
+ pinctrl-0 = <
+ &pinctrl_board_mmc0_slot0
+ &pinctrl_mmc0_slot0_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioC 2 0>;
+ };
+ };
+
+ pinctrl@fffff400 {
+ mmc0_slot0 {
+ pinctrl_board_mmc0_slot0: mmc0_slot0-board {
+ atmel,pins =
+ <2 2 0x0 0x5>; /* PC2 gpio CD pin pull up and deglitch */
+ };
+ };
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index e6391a4e6649..32a500a0e481 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -35,6 +35,13 @@
};
usart0: serial@fffb0000 {
+ pinctrl-0 =
+ <&pinctrl_usart0
+ &pinctrl_usart0_rts
+ &pinctrl_usart0_cts
+ &pinctrl_usart0_dtr_dsr
+ &pinctrl_usart0_dcd
+ &pinctrl_usart0_ri>;
status = "okay";
};
@@ -51,6 +58,29 @@
atmel,vbus-gpio = <&pioC 5 0>;
status = "okay";
};
+
+ mmc0: mmc@fffa8000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0_slot1
+ &pinctrl_mmc0_clk
+ &pinctrl_mmc0_slot1_cmd_dat0
+ &pinctrl_mmc0_slot1_dat1_3>;
+ status = "okay";
+ slot@1 {
+ reg = <1>;
+ bus-width = <4>;
+ cd-gpios = <&pioC 9 0>;
+ };
+ };
+
+ pinctrl@fffff400 {
+ mmc0_slot1 {
+ pinctrl_board_mmc0_slot1: mmc0_slot1-board {
+ atmel,pins =
+ <2 9 0x0 0x5>; /* PC9 gpio CD pin pull up and deglitch */
+ };
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi
new file mode 100644
index 000000000000..05a718fb83c4
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g25.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g25.dtsi - Device Tree Include file for AT91SAM9G25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G25 SoC";
+ compatible = "atmel, at91sam9g25, atmel,at91sam9x5";
+
+ ahb {
+ apb {
+ pinctrl@fffff400 {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe0399f 0xc000001c /* pioA */
+ 0x0007ffff 0x8000fe3f 0x00000000 /* pioB */
+ 0x80000000 0x07c0ffff 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index 877c08f06763..c5ab16fba059 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -7,55 +7,10 @@
* Licensed under GPLv2 or later.
*/
/dts-v1/;
-/include/ "at91sam9x5.dtsi"
-/include/ "at91sam9x5cm.dtsi"
+/include/ "at91sam9g25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
/ {
model = "Atmel AT91SAM9G25-EK";
compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
-
- chosen {
- bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
- };
-
- ahb {
- apb {
- dbgu: serial@fffff200 {
- status = "okay";
- };
-
- usart0: serial@f801c000 {
- status = "okay";
- };
-
- macb0: ethernet@f802c000 {
- phy-mode = "rmii";
- status = "okay";
- };
-
- i2c0: i2c@f8010000 {
- status = "okay";
- };
-
- i2c1: i2c@f8014000 {
- status = "okay";
- };
-
- i2c2: i2c@f8018000 {
- status = "okay";
- };
- };
-
- usb0: ohci@00600000 {
- status = "okay";
- num-ports = <2>;
- atmel,vbus-gpio = <&pioD 19 1
- &pioD 20 1
- >;
- };
-
- usb1: ehci@00700000 {
- status = "okay";
- };
- };
};
diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi
new file mode 100644
index 000000000000..f9d14a722794
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g35.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9g35.dtsi - Device Tree Include file for AT91SAM9G35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G35 SoC";
+ compatible = "atmel, at91sam9g35, atmel,at91sam9x5";
+
+ ahb {
+ apb {
+ pinctrl@fffff400 {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe0399f 0xc000000c /* pioA */
+ 0x000406ff 0x00047e3f 0x00000000 /* pioB */
+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9g35ek.dts b/arch/arm/boot/dts/at91sam9g35ek.dts
new file mode 100644
index 000000000000..95944bdd798d
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9g35ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9g35ek.dts - Device Tree file for AT91SAM9G35-EK board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9g35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G35-EK";
+ compatible = "atmel,at91sam9g35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 3add030d61f8..0741caeeced1 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -108,60 +108,243 @@
interrupts = <21 4 0>;
};
- pioA: gpio@fffff200 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff200 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pinctrl@fffff200 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff200 0xfffff200 0xa00>;
+
+ atmel,mux-mask = <
+ /* A B */
+ 0xffffffff 0xffc003ff /* pioA */
+ 0xffffffff 0x800f8f00 /* pioB */
+ 0xffffffff 0x00000e00 /* pioC */
+ 0xffffffff 0xff0c1381 /* pioD */
+ 0xffffffff 0x81ffff81 /* pioE */
+ >;
+
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <1 12 0x1 0x0 /* PB12 periph A */
+ 1 13 0x1 0x0>; /* PB13 periph A */
+ };
+ };
- pioB: gpio@fffff400 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ usart0 {
+ pinctrl_usart0: usart0-0 {
+ atmel,pins =
+ <1 19 0x1 0x1 /* PB19 periph A with pullup */
+ 1 18 0x1 0x0>; /* PB18 periph A */
+ };
+
+ pinctrl_usart0_rts: usart0_rts-0 {
+ atmel,pins =
+ <1 17 0x2 0x0>; /* PB17 periph B */
+ };
+
+ pinctrl_usart0_cts: usart0_cts-0 {
+ atmel,pins =
+ <1 15 0x2 0x0>; /* PB15 periph B */
+ };
+ };
- pioC: gpio@fffff600 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <4 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ uart1 {
+ pinctrl_usart1: usart1-0 {
+ atmel,pins =
+ <1 4 0x1 0x1 /* PB4 periph A with pullup */
+ 1 5 0x1 0x0>; /* PB5 periph A */
+ };
+
+ pinctrl_usart1_rts: usart1_rts-0 {
+ atmel,pins =
+ <3 16 0x1 0x0>; /* PD16 periph A */
+ };
+
+ pinctrl_usart1_cts: usart1_cts-0 {
+ atmel,pins =
+ <3 17 0x1 0x0>; /* PD17 periph A */
+ };
+ };
- pioD: gpio@fffff800 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <5 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ usart2 {
+ pinctrl_usart2: usart2-0 {
+ atmel,pins =
+ <1 6 0x1 0x1 /* PB6 periph A with pullup */
+ 1 7 0x1 0x0>; /* PB7 periph A */
+ };
+
+ pinctrl_usart2_rts: usart2_rts-0 {
+ atmel,pins =
+ <2 9 0x2 0x0>; /* PC9 periph B */
+ };
+
+ pinctrl_usart2_cts: usart2_cts-0 {
+ atmel,pins =
+ <2 11 0x2 0x0>; /* PC11 periph B */
+ };
+ };
- pioE: gpio@fffffa00 {
- compatible = "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
- interrupts = <5 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ usart3 {
+ pinctrl_usart3: usart3-0 {
+ atmel,pins =
+ <1 8 0x1 0x1 /* PB9 periph A with pullup */
+ 1 9 0x1 0x0>; /* PB8 periph A */
+ };
+
+ pinctrl_usart3_rts: usart3_rts-0 {
+ atmel,pins =
+ <0 23 0x2 0x0>; /* PA23 periph B */
+ };
+
+ pinctrl_usart3_cts: usart3_cts-0 {
+ atmel,pins =
+ <0 24 0x2 0x0>; /* PA24 periph B */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <2 8 0x0 0x1 /* PC8 gpio RDY pin pull_up*/
+ 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+ };
+ };
+
+ macb {
+ pinctrl_macb_rmii: macb_rmii-0 {
+ atmel,pins =
+ <0 10 0x1 0x0 /* PA10 periph A */
+ 0 11 0x1 0x0 /* PA11 periph A */
+ 0 12 0x1 0x0 /* PA12 periph A */
+ 0 13 0x1 0x0 /* PA13 periph A */
+ 0 14 0x1 0x0 /* PA14 periph A */
+ 0 15 0x1 0x0 /* PA15 periph A */
+ 0 16 0x1 0x0 /* PA16 periph A */
+ 0 17 0x1 0x0 /* PA17 periph A */
+ 0 18 0x1 0x0 /* PA18 periph A */
+ 0 19 0x1 0x0>; /* PA19 periph A */
+ };
+
+ pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+ atmel,pins =
+ <0 6 0x2 0x0 /* PA6 periph B */
+ 0 7 0x2 0x0 /* PA7 periph B */
+ 0 8 0x2 0x0 /* PA8 periph B */
+ 0 9 0x2 0x0 /* PA9 periph B */
+ 0 27 0x2 0x0 /* PA27 periph B */
+ 0 28 0x2 0x0 /* PA28 periph B */
+ 0 29 0x2 0x0 /* PA29 periph B */
+ 0 30 0x2 0x0>; /* PA30 periph B */
+ };
+ };
+
+ mmc0 {
+ pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+ atmel,pins =
+ <0 0 0x1 0x0 /* PA0 periph A */
+ 0 1 0x1 0x1 /* PA1 periph A with pullup */
+ 0 2 0x1 0x1>; /* PA2 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 3 0x1 0x1 /* PA3 periph A with pullup */
+ 0 4 0x1 0x1 /* PA4 periph A with pullup */
+ 0 5 0x1 0x1>; /* PA5 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+ atmel,pins =
+ <0 6 0x1 0x1 /* PA6 periph A with pullup */
+ 0 7 0x1 0x1 /* PA7 periph A with pullup */
+ 0 8 0x1 0x1 /* PA8 periph A with pullup */
+ 0 9 0x1 0x1>; /* PA9 periph A with pullup */
+ };
+ };
+
+ mmc1 {
+ pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+ atmel,pins =
+ <0 31 0x1 0x0 /* PA31 periph A */
+ 0 22 0x1 0x1 /* PA22 periph A with pullup */
+ 0 23 0x1 0x1>; /* PA23 periph A with pullup */
+ };
+
+ pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 24 0x1 0x1 /* PA24 periph A with pullup */
+ 0 25 0x1 0x1 /* PA25 periph A with pullup */
+ 0 26 0x1 0x1>; /* PA26 periph A with pullup */
+ };
+
+ pinctrl_mmc1_slot0_dat4_7: mmc1_slot0_dat4_7-0 {
+ atmel,pins =
+ <0 27 0x1 0x1 /* PA27 periph A with pullup */
+ 0 28 0x1 0x1 /* PA28 periph A with pullup */
+ 0 29 0x1 0x1 /* PA29 periph A with pullup */
+ 0 20 0x1 0x1>; /* PA30 periph A with pullup */
+ };
+ };
+
+ pioA: gpio@fffff200 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff200 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff400 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff600 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <4 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio@fffff800 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <5 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioE: gpio@fffffa00 {
+ compatible = "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <5 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
dbgu: serial@ffffee00 {
compatible = "atmel,at91sam9260-usart";
reg = <0xffffee00 0x200>;
interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
status = "disabled";
};
@@ -171,6 +354,8 @@
interrupts = <7 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart0>;
status = "disabled";
};
@@ -180,6 +365,8 @@
interrupts = <8 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
status = "disabled";
};
@@ -189,6 +376,8 @@
interrupts = <9 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2>;
status = "disabled";
};
@@ -198,6 +387,8 @@
interrupts = <10 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart3>;
status = "disabled";
};
@@ -205,6 +396,8 @@
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xfffbc000 0x100>;
interrupts = <25 4 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb_rmii>;
status = "disabled";
};
@@ -262,6 +455,24 @@
trigger-value = <0x6>;
};
};
+
+ mmc0: mmc@fff80000 {
+ compatible = "atmel,hsmci";
+ reg = <0xfff80000 0x600>;
+ interrupts = <11 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@fffd0000 {
+ compatible = "atmel,hsmci";
+ reg = <0xfffd0000 0x600>;
+ interrupts = <29 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
nand0: nand@40000000 {
@@ -273,6 +484,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioC 8 0
&pioC 14 0
0
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index 15e1dd43f625..20c31913c270 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -39,6 +39,10 @@
};
usart1: serial@fff90000 {
+ pinctrl-0 =
+ <&pinctrl_usart1
+ &pinctrl_usart1_rts
+ &pinctrl_usart1_cts>;
status = "okay";
};
@@ -54,6 +58,50 @@
i2c1: i2c@fff88000 {
status = "okay";
};
+
+ mmc0: mmc@fff80000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 10 0>;
+ };
+ };
+
+ mmc1: mmc@fffd0000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc1
+ &pinctrl_mmc1_slot0_clk_cmd_dat0
+ &pinctrl_mmc1_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 11 0>;
+ wp-gpios = <&pioD 29 0>;
+ };
+ };
+
+ pinctrl@fffff200 {
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <3 10 0x0 0x5>; /* PD10 gpio CD pin pull up and deglitch */
+ };
+ };
+
+ mmc1 {
+ pinctrl_board_mmc1: mmc1-board {
+ atmel,pins =
+ <3 11 0x0 0x5 /* PD11 gpio CD pin pull up and deglitch */
+ 3 29 0x0 0x1>; /* PD29 gpio WP pin pull up */
+ };
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 82508d68aa7e..e9efb34f4379 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -84,6 +84,15 @@
reg = <0xfffffe10 0x10>;
};
+ mmc0: mmc@f0008000 {
+ compatible = "atmel,hsmci";
+ reg = <0xf0008000 0x600>;
+ interrupts = <12 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
tcb0: timer@f8008000 {
compatible = "atmel,at91sam9x5-tcb";
reg = <0xf8008000 0x100>;
@@ -102,50 +111,186 @@
interrupts = <20 4 0>;
};
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pinctrl@fffff400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff400 0xfffff400 0x800>;
- pioB: gpio@fffff600 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe07983 0x00000000 /* pioA */
+ 0x00040000 0x00047e0f 0x00000000 /* pioB */
+ 0xfdffffff 0x07c00000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
- pioC: gpio@fffff800 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <0 9 0x1 0x0 /* PA9 periph A */
+ 0 10 0x1 0x1>; /* PA10 periph with pullup */
+ };
+ };
- pioD: gpio@fffffa00 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ usart0 {
+ pinctrl_usart0: usart0-0 {
+ atmel,pins =
+ <0 1 0x1 0x1 /* PA1 periph A with pullup */
+ 0 0 0x1 0x0>; /* PA0 periph A */
+ };
+
+ pinctrl_usart0_rts: usart0_rts-0 {
+ atmel,pins =
+ <0 2 0x1 0x0>; /* PA2 periph A */
+ };
+
+ pinctrl_usart0_cts: usart0_cts-0 {
+ atmel,pins =
+ <0 3 0x1 0x0>; /* PA3 periph A */
+ };
+ };
+
+ usart1 {
+ pinctrl_usart1: usart1-0 {
+ atmel,pins =
+ <0 6 0x1 0x1 /* PA6 periph A with pullup */
+ 0 5 0x1 0x0>; /* PA5 periph A */
+ };
+ };
+
+ usart2 {
+ pinctrl_usart2: usart2-0 {
+ atmel,pins =
+ <0 8 0x1 0x1 /* PA8 periph A with pullup */
+ 0 7 0x1 0x0>; /* PA7 periph A */
+ };
+
+ pinctrl_usart2_rts: usart2_rts-0 {
+ atmel,pins =
+ <1 0 0x2 0x0>; /* PB0 periph B */
+ };
+
+ pinctrl_usart2_cts: usart2_cts-0 {
+ atmel,pins =
+ <1 1 0x2 0x0>; /* PB1 periph B */
+ };
+ };
+
+ usart3 {
+ pinctrl_usart3: usart3-0 {
+ atmel,pins =
+ <2 23 0x2 0x1 /* PC23 periph B with pullup */
+ 2 22 0x2 0x0>; /* PC22 periph B */
+ };
+
+ pinctrl_usart3_rts: usart3_rts-0 {
+ atmel,pins =
+ <2 24 0x2 0x0>; /* PC24 periph B */
+ };
+
+ pinctrl_usart3_cts: usart3_cts-0 {
+ atmel,pins =
+ <2 25 0x2 0x0>; /* PC25 periph B */
+ };
+ };
+
+ uart0 {
+ pinctrl_uart0: uart0-0 {
+ atmel,pins =
+ <2 9 0x3 0x1 /* PC9 periph C with pullup */
+ 2 8 0x3 0x0>; /* PC8 periph C */
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1: uart1-0 {
+ atmel,pins =
+ <2 16 0x3 0x1 /* PC17 periph C with pullup */
+ 2 17 0x3 0x0>; /* PC16 periph C */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <3 5 0x0 0x1 /* PD5 gpio RDY pin pull_up*/
+ 3 4 0x0 0x1>; /* PD4 gpio enable pin pull_up */
+ };
+ };
+
+ mmc0 {
+ pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+ atmel,pins =
+ <0 17 0x1 0x0 /* PA17 periph A */
+ 0 16 0x1 0x1 /* PA16 periph A with pullup */
+ 0 15 0x1 0x1>; /* PA15 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 18 0x1 0x1 /* PA18 periph A with pullup */
+ 0 19 0x1 0x1 /* PA19 periph A with pullup */
+ 0 20 0x1 0x1>; /* PA20 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+ atmel,pins =
+ <0 11 0x2 0x1 /* PA11 periph B with pullup */
+ 0 12 0x2 0x1 /* PA12 periph B with pullup */
+ 0 13 0x2 0x1 /* PA13 periph B with pullup */
+ 0 14 0x2 0x1>; /* PA14 periph B with pullup */
+ };
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio@fffffa00 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
dbgu: serial@fffff200 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfffff200 0x200>;
interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
status = "disabled";
};
@@ -155,6 +300,8 @@
interrupts = <5 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart0>;
status = "disabled";
};
@@ -164,6 +311,8 @@
interrupts = <6 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
status = "disabled";
};
@@ -173,6 +322,8 @@
interrupts = <7 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2>;
status = "disabled";
};
@@ -182,6 +333,8 @@
interrupts = <8 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart3>;
status = "disabled";
};
@@ -215,6 +368,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioD 5 0
&pioD 4 0
0
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index 912b2c283d6f..0376bf4fd66b 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -45,6 +45,28 @@
i2c1: i2c@f8014000 {
status = "okay";
};
+
+ mmc0: mmc@f0008000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioA 7 0>;
+ };
+ };
+
+ pinctrl@fffff400 {
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <0 7 0x0 0x5>; /* PA7 gpio CD pin pull up and deglitch */
+ };
+ };
+ };
};
nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
new file mode 100644
index 000000000000..54eb33ba6d22
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x25.dtsi
@@ -0,0 +1,49 @@
+/*
+ * at91sam9x25.dtsi - Device Tree Include file for AT91SAM9X25 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9X25 SoC";
+ compatible = "atmel, at91sam9x25, atmel,at91sam9x5";
+
+ ahb {
+ apb {
+ pinctrl@fffff400 {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe03fff 0xc000001c /* pioA */
+ 0x0007ffff 0x00047e3f 0x00000000 /* pioB */
+ 0x80000000 0xfffd0000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+
+ macb1 {
+ pinctrl_macb1_rmii: macb1_rmii-0 {
+ atmel,pins =
+ <2 16 0x2 0x0 /* PC16 periph B */
+ 2 18 0x2 0x0 /* PC18 periph B */
+ 2 19 0x2 0x0 /* PC19 periph B */
+ 2 20 0x2 0x0 /* PC20 periph B */
+ 2 21 0x2 0x0 /* PC21 periph B */
+ 2 27 0x2 0x0 /* PC27 periph B */
+ 2 28 0x2 0x0 /* PC28 periph B */
+ 2 29 0x2 0x0 /* PC29 periph B */
+ 2 30 0x2 0x0 /* PC30 periph B */
+ 2 31 0x2 0x0>; /* PC31 periph B */
+ };
+ };
+ };
+
+ macb1: ethernet@f8030000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb1_rmii>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9x25ek.dts b/arch/arm/boot/dts/at91sam9x25ek.dts
new file mode 100644
index 000000000000..af907eaa1f25
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x25ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x25ek.dts - Device Tree file for AT91SAM9X25-EK board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x25.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9G25-EK";
+ compatible = "atmel,at91sam9x25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi
new file mode 100644
index 000000000000..fb102d6126ce
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x35.dtsi
@@ -0,0 +1,28 @@
+/*
+ * at91sam9x35.dtsi - Device Tree Include file for AT91SAM9X35 SoC
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+/include/ "at91sam9x5.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9X35 SoC";
+ compatible = "atmel, at91sam9x35, atmel,at91sam9x5";
+
+ ahb {
+ apb {
+ pinctrl@fffff400 {
+ atmel,mux-mask = <
+ /* A B C */
+ 0xffffffff 0xffe03fff 0xc000000c /* pioA */
+ 0x000406ff 0x00047e3f 0x00000000 /* pioB */
+ 0xfdffffff 0x00000000 0xb83fffff /* pioC */
+ 0x003fffff 0x003f8000 0x00000000 /* pioD */
+ >;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/at91sam9x35ek.dts b/arch/arm/boot/dts/at91sam9x35ek.dts
new file mode 100644
index 000000000000..5ccb607b5414
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x35ek.dts
@@ -0,0 +1,16 @@
+/*
+ * at91sam9x35ek.dts - Device Tree file for AT91SAM9X35-EK board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+/include/ "at91sam9x35.dtsi"
+/include/ "at91sam9x5ek.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9X35-EK";
+ compatible = "atmel,at91sam9x35ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+};
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 03fc136421c5..7ee49e8daf98 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -111,50 +111,244 @@
interrupts = <21 4 0>;
};
- pioA: gpio@fffff400 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff400 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ pinctrl@fffff400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
+ ranges = <0xfffff400 0xfffff400 0x800>;
+
+ /* shared pinctrl settings */
+ dbgu {
+ pinctrl_dbgu: dbgu-0 {
+ atmel,pins =
+ <0 9 0x1 0x0 /* PA9 periph A */
+ 0 10 0x1 0x1>; /* PA10 periph A with pullup */
+ };
+ };
- pioB: gpio@fffff600 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff600 0x100>;
- interrupts = <2 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ usart0 {
+ pinctrl_usart0: usart0-0 {
+ atmel,pins =
+ <0 0 0x1 0x1 /* PA0 periph A with pullup */
+ 0 1 0x1 0x0>; /* PA1 periph A */
+ };
+
+ pinctrl_usart0_rts: usart0_rts-0 {
+ atmel,pins =
+ <0 2 0x1 0x0>; /* PA2 periph A */
+ };
+
+ pinctrl_usart0_cts: usart0_cts-0 {
+ atmel,pins =
+ <0 3 0x1 0x0>; /* PA3 periph A */
+ };
+ };
+
+ usart1 {
+ pinctrl_usart1: usart1-0 {
+ atmel,pins =
+ <0 5 0x1 0x1 /* PA5 periph A with pullup */
+ 0 6 0x1 0x0>; /* PA6 periph A */
+ };
+
+ pinctrl_usart1_rts: usart1_rts-0 {
+ atmel,pins =
+ <3 27 0x3 0x0>; /* PC27 periph C */
+ };
+
+ pinctrl_usart1_cts: usart1_cts-0 {
+ atmel,pins =
+ <3 28 0x3 0x0>; /* PC28 periph C */
+ };
+ };
+
+ usart2 {
+ pinctrl_usart2: usart2-0 {
+ atmel,pins =
+ <0 7 0x1 0x1 /* PA7 periph A with pullup */
+ 0 8 0x1 0x0>; /* PA8 periph A */
+ };
+
+ pinctrl_uart2_rts: uart2_rts-0 {
+ atmel,pins =
+ <0 0 0x2 0x0>; /* PB0 periph B */
+ };
+
+ pinctrl_uart2_cts: uart2_cts-0 {
+ atmel,pins =
+ <0 1 0x2 0x0>; /* PB1 periph B */
+ };
+ };
+
+ usart3 {
+ pinctrl_uart3: usart3-0 {
+ atmel,pins =
+ <3 23 0x2 0x1 /* PC22 periph B with pullup */
+ 3 23 0x2 0x0>; /* PC23 periph B */
+ };
+
+ pinctrl_usart3_rts: usart3_rts-0 {
+ atmel,pins =
+ <3 24 0x2 0x0>; /* PC24 periph B */
+ };
+
+ pinctrl_usart3_cts: usart3_cts-0 {
+ atmel,pins =
+ <3 25 0x2 0x0>; /* PC25 periph B */
+ };
+ };
+
+ uart0 {
+ pinctrl_uart0: uart0-0 {
+ atmel,pins =
+ <3 8 0x3 0x0 /* PC8 periph C */
+ 3 9 0x3 0x1>; /* PC9 periph C with pullup */
+ };
+ };
+
+ uart1 {
+ pinctrl_uart1: uart1-0 {
+ atmel,pins =
+ <3 16 0x3 0x0 /* PC16 periph C */
+ 3 17 0x3 0x1>; /* PC17 periph C with pullup */
+ };
+ };
+
+ nand {
+ pinctrl_nand: nand-0 {
+ atmel,pins =
+ <3 4 0x0 0x1 /* PD5 gpio RDY pin pull_up */
+ 3 5 0x0 0x1>; /* PD4 gpio enable pin pull_up */
+ };
+ };
+
+ macb0 {
+ pinctrl_macb0_rmii: macb0_rmii-0 {
+ atmel,pins =
+ <1 0 0x1 0x0 /* PB0 periph A */
+ 1 1 0x1 0x0 /* PB1 periph A */
+ 1 2 0x1 0x0 /* PB2 periph A */
+ 1 3 0x1 0x0 /* PB3 periph A */
+ 1 4 0x1 0x0 /* PB4 periph A */
+ 1 5 0x1 0x0 /* PB5 periph A */
+ 1 6 0x1 0x0 /* PB6 periph A */
+ 1 7 0x1 0x0 /* PB7 periph A */
+ 1 9 0x1 0x0 /* PB9 periph A */
+ 1 10 0x1 0x0>; /* PB10 periph A */
+ };
+
+ pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
+ atmel,pins =
+ <1 8 0x1 0x0 /* PA8 periph A */
+ 1 11 0x1 0x0 /* PA11 periph A */
+ 1 12 0x1 0x0 /* PA12 periph A */
+ 1 13 0x1 0x0 /* PA13 periph A */
+ 1 14 0x1 0x0 /* PA14 periph A */
+ 1 15 0x1 0x0 /* PA15 periph A */
+ 1 16 0x1 0x0 /* PA16 periph A */
+ 1 17 0x1 0x0>; /* PA17 periph A */
+ };
+ };
+
+ mmc0 {
+ pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+ atmel,pins =
+ <0 17 0x1 0x0 /* PA17 periph A */
+ 0 16 0x1 0x1 /* PA16 periph A with pullup */
+ 0 15 0x1 0x1>; /* PA15 periph A with pullup */
+ };
+
+ pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 18 0x1 0x1 /* PA18 periph A with pullup */
+ 0 19 0x1 0x1 /* PA19 periph A with pullup */
+ 0 20 0x1 0x1>; /* PA20 periph A with pullup */
+ };
+ };
+
+ mmc1 {
+ pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+ atmel,pins =
+ <0 13 0x2 0x0 /* PA13 periph B */
+ 0 12 0x2 0x1 /* PA12 periph B with pullup */
+ 0 11 0x2 0x1>; /* PA11 periph B with pullup */
+ };
+
+ pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+ atmel,pins =
+ <0 2 0x2 0x1 /* PA2 periph B with pullup */
+ 0 3 0x2 0x1 /* PA3 periph B with pullup */
+ 0 4 0x2 0x1>; /* PA4 periph B with pullup */
+ };
+ };
+
+ pioA: gpio@fffff400 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff400 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioB: gpio@fffff600 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff600 0x200>;
+ interrupts = <2 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ #gpio-lines = <19>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioC: gpio@fffff800 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffff800 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pioD: gpio@fffffa00 {
+ compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
+ reg = <0xfffffa00 0x200>;
+ interrupts = <3 4 1>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ #gpio-lines = <22>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
- pioC: gpio@fffff800 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffff800 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ mmc0: mmc@f0008000 {
+ compatible = "atmel,hsmci";
+ reg = <0xf0008000 0x600>;
+ interrupts = <12 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
- pioD: gpio@fffffa00 {
- compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
- reg = <0xfffffa00 0x100>;
- interrupts = <3 4 1>;
- #gpio-cells = <2>;
- gpio-controller;
- interrupt-controller;
- #interrupt-cells = <2>;
+ mmc1: mmc@f000c000 {
+ compatible = "atmel,hsmci";
+ reg = <0xf000c000 0x600>;
+ interrupts = <26 4 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
dbgu: serial@fffff200 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfffff200 0x200>;
interrupts = <1 4 7>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dbgu>;
status = "disabled";
};
@@ -164,6 +358,8 @@
interrupts = <5 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart0>;
status = "disabled";
};
@@ -173,6 +369,8 @@
interrupts = <6 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
status = "disabled";
};
@@ -182,6 +380,8 @@
interrupts = <7 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2>;
status = "disabled";
};
@@ -189,6 +389,8 @@
compatible = "cdns,at32ap7000-macb", "cdns,macb";
reg = <0xf802c000 0x100>;
interrupts = <24 4 3>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb0_rmii>;
status = "disabled";
};
@@ -273,6 +475,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_nand>;
gpios = <&pioD 5 0
&pioD 4 0
0
diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi
new file mode 100644
index 000000000000..8a7cf1d9cf5d
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi
@@ -0,0 +1,101 @@
+/*
+ * at91sam9x5ek.dtsi - Device Tree file for AT91SAM9x5CM Base board
+ *
+ * Copyright (C) 2012 Atmel,
+ * 2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/include/ "at91sam9x5cm.dtsi"
+
+/ {
+ model = "Atmel AT91SAM9X5-EK";
+ compatible = "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+ };
+
+ ahb {
+ apb {
+ mmc0: mmc@f0008000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc0
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 15 0>;
+ };
+ };
+
+ mmc1: mmc@f000c000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc1
+ &pinctrl_mmc1_slot0_clk_cmd_dat0
+ &pinctrl_mmc1_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 14 0>;
+ };
+ };
+
+ dbgu: serial@fffff200 {
+ status = "okay";
+ };
+
+ usart0: serial@f801c000 {
+ status = "okay";
+ };
+
+ macb0: ethernet@f802c000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ i2c0: i2c@f8010000 {
+ status = "okay";
+ };
+
+ i2c1: i2c@f8014000 {
+ status = "okay";
+ };
+
+ i2c2: i2c@f8018000 {
+ status = "okay";
+ };
+
+ pinctrl@fffff400 {
+ mmc0 {
+ pinctrl_board_mmc0: mmc0-board {
+ atmel,pins =
+ <3 15 0x0 0x5>; /* PD15 gpio CD pin pull up and deglitch */
+ };
+ };
+
+ mmc1 {
+ pinctrl_board_mmc1: mmc1-board {
+ atmel,pins =
+ <3 14 0x0 0x5>; /* PD14 gpio CD pin pull up and deglitch */
+ };
+ };
+ };
+ };
+
+ usb0: ohci@00600000 {
+ status = "okay";
+ num-ports = <2>;
+ atmel,vbus-gpio = <&pioD 19 1
+ &pioD 20 1
+ >;
+ };
+
+ usb1: ehci@00700000 {
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/pm9g45.dts
new file mode 100644
index 000000000000..387fedb58988
--- /dev/null
+++ b/arch/arm/boot/dts/pm9g45.dts
@@ -0,0 +1,165 @@
+/*
+ * pm9g45.dts - Device Tree file for Ronetix pm9g45 board
+ *
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+ model = "Ronetix pm9g45";
+ compatible = "ronetix,pm9g45", "atmel,at91sam9g45", "atmel,at91sam9";
+
+ chosen {
+ bootargs = "console=ttyS0,115200";
+ };
+
+ memory {
+ reg = <0x70000000 0x8000000>;
+ };
+
+ 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";
+ };
+
+ pinctrl@fffff200 {
+
+ board {
+ pinctrl_board_nand: nand0-board {
+ atmel,pins =
+ <3 3 0x0 0x1 /* PD3 gpio RDY pin pull_up*/
+ 2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+ };
+ };
+
+ mmc {
+ pinctrl_board_mmc: mmc0-board {
+ atmel,pins =
+ <3 6 0x0 0x5>; /* PD6 gpio CD pin pull_up and deglitch */
+ };
+ };
+ };
+
+ mmc0: mmc@fff80000 {
+ pinctrl-0 = <
+ &pinctrl_board_mmc
+ &pinctrl_mmc0_slot0_clk_cmd_dat0
+ &pinctrl_mmc0_slot0_dat1_3>;
+ status = "okay";
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ cd-gpios = <&pioD 6 0>;
+ };
+ };
+
+ macb0: ethernet@fffbc000 {
+ phy-mode = "rmii";
+ status = "okay";
+ };
+
+ };
+
+ nand0: nand@40000000 {
+ nand-bus-width = <8>;
+ nand-ecc-mode = "soft";
+ nand-on-flash-bbt;
+ pinctrl-0 = <&pinctrl_board_nand>;
+
+ gpios = <&pioD 3 0
+ &pioC 14 0
+ 0
+ >;
+
+ status = "okay";
+
+ at91bootstrap@0 {
+ label = "at91bootstrap";
+ reg = <0x0 0x20000>;
+ };
+
+ barebox@20000 {
+ label = "barebox";
+ reg = <0x20000 0x40000>;
+ };
+
+ bareboxenv@60000 {
+ label = "bareboxenv";
+ reg = <0x60000 0x1A0000>;
+ };
+
+ kernel@200000 {
+ label = "bareboxenv2";
+ reg = <0x200000 0x300000>;
+ };
+
+ kernel@500000 {
+ label = "root";
+ reg = <0x500000 0x400000>;
+ };
+
+ data@900000 {
+ label = "data";
+ reg = <0x900000 0x8340000>;
+ };
+ };
+
+ usb0: ohci@00700000 {
+ status = "okay";
+ num-ports = <2>;
+ };
+
+ usb1: ehci@00800000 {
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led0 {
+ label = "led0";
+ gpios = <&pioD 0 1>;
+ linux,default-trigger = "nand-disk";
+ };
+
+ led1 {
+ label = "led1";
+ gpios = <&pioD 31 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ right {
+ label = "SW4";
+ gpios = <&pioE 7 1>;
+ linux,code = <106>;
+ };
+
+ up {
+ label = "SW3";
+ gpios = <&pioE 8 1>;
+ linux,code = <103>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index dd4358bc26e2..2e4c5727468e 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -181,6 +181,10 @@
status = "okay";
};
+ gpio@d8400000 {
+ status = "okay";
+ };
+
i2c0: i2c@e0280000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 419ea7413d23..7cd25eb4f8e0 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -70,6 +70,12 @@
status = "disabled";
};
+ pinmux: pinmux@e0700000 {
+ compatible = "st,spear1310-pinmux";
+ reg = <0xe0700000 0x1000>;
+ #gpio-range-cells = <2>;
+ };
+
spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>;
@@ -179,6 +185,27 @@
thermal@e07008c4 {
st,thermal-flags = <0x7000>;
};
+
+ gpiopinctrl: gpio@d8400000 {
+ compatible = "st,spear-plgpio";
+ reg = <0xd8400000 0x1000>;
+ interrupts = <0 100 0x4>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinmux 0 246>;
+ status = "disabled";
+
+ st-plgpio,ngpio = <246>;
+ st-plgpio,enb-reg = <0xd0>;
+ st-plgpio,wdata-reg = <0x90>;
+ st-plgpio,dir-reg = <0xb0>;
+ st-plgpio,ie-reg = <0x30>;
+ st-plgpio,rdata-reg = <0x70>;
+ st-plgpio,mis-reg = <0x10>;
+ st-plgpio,eit-reg = <0x50>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index c9a54e06fb68..045f7123ffac 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -193,6 +193,10 @@
status = "okay";
};
+ gpio@e2800000 {
+ status = "okay";
+ };
+
i2c0: i2c@e0280000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index d71fe2a68f09..6c09eb0a1b2b 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -24,6 +24,12 @@
status = "disabled";
};
+ pinmux: pinmux@e0700000 {
+ compatible = "st,spear1340-pinmux";
+ reg = <0xe0700000 0x1000>;
+ #gpio-range-cells = <2>;
+ };
+
spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>;
@@ -51,6 +57,26 @@
thermal@e07008c4 {
st,thermal-flags = <0x2a00>;
};
+
+ gpiopinctrl: gpio@e2800000 {
+ compatible = "st,spear-plgpio";
+ reg = <0xe2800000 0x1000>;
+ interrupts = <0 107 0x4>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinmux 0 252>;
+ status = "disabled";
+
+ st-plgpio,ngpio = <250>;
+ st-plgpio,wdata-reg = <0x40>;
+ st-plgpio,dir-reg = <0x00>;
+ st-plgpio,ie-reg = <0x80>;
+ st-plgpio,rdata-reg = <0x20>;
+ st-plgpio,mis-reg = <0xa0>;
+ st-plgpio,eit-reg = <0x60>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index 62fc4fb3e5f9..930303e48df9 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -22,9 +22,10 @@
0xb0000000 0xb0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
- pinmux@b4000000 {
+ pinmux: pinmux@b4000000 {
compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>;
+ #gpio-range-cells = <2>;
};
fsmc: flash@44000000 {
@@ -75,6 +76,25 @@
reg = <0xb2200000 0x1000>;
status = "disabled";
};
+
+ gpiopinctrl: gpio@b4000000 {
+ compatible = "st,spear-plgpio";
+ reg = <0xb4000000 0x1000>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinmux 0 102>;
+ status = "disabled";
+
+ st-plgpio,ngpio = <102>;
+ st-plgpio,enb-reg = <0x10>;
+ st-plgpio,wdata-reg = <0x20>;
+ st-plgpio,dir-reg = <0x30>;
+ st-plgpio,ie-reg = <0x50>;
+ st-plgpio,rdata-reg = <0x40>;
+ st-plgpio,mis-reg = <0x60>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
index 082328bd64ab..ad4bfc68ee05 100644
--- a/arch/arm/boot/dts/spear320-evb.dts
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -164,6 +164,10 @@
status = "okay";
};
+ gpio@b3000000 {
+ status = "okay";
+ };
+
i2c0: i2c@d0180000 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 1f49d69595a0..67d7ada71275 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -21,9 +21,10 @@
ranges = <0x40000000 0x40000000 0x80000000
0xd0000000 0xd0000000 0x30000000>;
- pinmux@b3000000 {
+ pinmux: pinmux@b3000000 {
compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>;
+ #gpio-range-cells = <2>;
};
clcd@90000000 {
@@ -90,6 +91,26 @@
reg = <0xa4000000 0x1000>;
status = "disabled";
};
+
+ gpiopinctrl: gpio@b3000000 {
+ compatible = "st,spear-plgpio";
+ reg = <0xb3000000 0x1000>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinmux 0 102>;
+ status = "disabled";
+
+ st-plgpio,ngpio = <102>;
+ st-plgpio,enb-reg = <0x24>;
+ st-plgpio,wdata-reg = <0x34>;
+ st-plgpio,dir-reg = <0x44>;
+ st-plgpio,ie-reg = <0x64>;
+ st-plgpio,rdata-reg = <0x54>;
+ st-plgpio,mis-reg = <0x84>;
+ st-plgpio,eit-reg = <0x94>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index f0ba901676ac..a20d4ff3fb3c 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -523,12 +523,12 @@
};
temperature-sensor@4c {
- compatible = "nct1008";
+ compatible = "onnn,nct1008";
reg = <0x4c>;
};
magnetometer@c {
- compatible = "ak8975";
+ compatible = "ak,ak8975";
reg = <0xc>;
interrupt-parent = <&gpio>;
interrupts = <109 0x04>; /* gpio PN5 */
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index df13a3ffff35..9d2d3ba339ff 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -162,7 +162,6 @@ static struct clock_event_device sp804_clockevent = {
.set_mode = sp804_set_mode,
.set_next_event = sp804_set_next_event,
.rating = 300,
- .cpumask = cpu_all_mask,
};
static struct irqaction sp804_timer_irq = {
@@ -185,6 +184,7 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
evt->name = name;
evt->irq = irq;
+ evt->cpumask = cpu_possible_mask;
setup_irq(irq, &sp804_timer_irq);
clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 67bc571ed0c3..b175577d7abb 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -111,6 +111,7 @@ CONFIG_I2C=y
CONFIG_I2C_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_ATMEL=y
+CONFIG_PINCTRL_AT91=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_AT91SAM9X_WATCHDOG=y
diff --git a/arch/arm/include/asm/hardware/sp810.h b/arch/arm/include/asm/hardware/sp810.h
index 6b9b077d86b3..afd7e916472f 100644
--- a/arch/arm/include/asm/hardware/sp810.h
+++ b/arch/arm/include/asm/hardware/sp810.h
@@ -56,6 +56,8 @@
#define SCCTRL_TIMEREN1SEL_REFCLK (0 << 17)
#define SCCTRL_TIMEREN1SEL_TIMCLK (1 << 17)
+#define SCCTRL_TIMERENnSEL_SHIFT(n) (15 + ((n) * 2))
+
static inline void sysctl_soft_reset(void __iomem *base)
{
/* switch to slow mode */
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 42f042ee4ada..652b56086de7 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -374,7 +374,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
#ifdef CONFIG_MMU
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
extern int devmem_is_allowed(unsigned long pfn);
#endif
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index aeae9c609df4..6d65ba222db9 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -11,6 +11,8 @@
#ifndef __ASMARM_PROM_H
#define __ASMARM_PROM_H
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
#ifdef CONFIG_OF
extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 043624219b55..e34c1bdb804d 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -494,8 +494,17 @@ endif
comment "Generic Board Type"
+config MACH_AT91RM9200_DT
+ bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
+ depends on SOC_AT91RM9200
+ select USE_OF
+ help
+ Select this if you want to experiment device-tree with
+ an Atmel RM9200 Evaluation Kit.
+
config MACH_AT91SAM_DT
bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+ depends on SOC_AT91SAM9
select USE_OF
help
Select this if you want to experiment device-tree with
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 3bb7a51efc9d..b38a1dcb79b8 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
# AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91RM9200_DT) += board-rm9200-dt.o
obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
# AT91X40 board-specific support
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 5269825194a8..6cceb42a4c33 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -194,6 +194,24 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_ID("pioB", &pioB_clk),
CLKDEV_CON_ID("pioC", &pioC_clk),
CLKDEV_CON_ID("pioD", &pioD_clk),
+ /* usart lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+ CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk),
+ CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk),
+ /* tc lookup table for DT entries */
+ CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
+ CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
+ CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
+ CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk),
+ CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk),
+ CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
+ CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -361,10 +379,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
0 /* Advanced Interrupt Controller (IRQ6) */
};
-struct at91_init_soc __initdata at91rm9200_soc = {
+AT91_SOC_START(rm9200)
.map_io = at91rm9200_map_io,
.default_irq_priority = at91rm9200_default_irq_priority,
.ioremap_registers = at91rm9200_ioremap_registers,
.register_clocks = at91rm9200_register_clocks,
.init = at91rm9200_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index aaa443b48c91..cafe98836c8a 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -24,6 +24,9 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/mach/time.h>
@@ -91,7 +94,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
static struct irqaction at91rm9200_timer_irq = {
.name = "at91_tick",
.flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = at91rm9200_timer_interrupt
+ .handler = at91rm9200_timer_interrupt,
+ .irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
static cycle_t read_clk32k(struct clocksource *cs)
@@ -179,8 +183,60 @@ static struct clock_event_device clkevt = {
void __iomem *at91_st_base;
EXPORT_SYMBOL_GPL(at91_st_base);
+#ifdef CONFIG_OF
+static struct of_device_id at91rm9200_st_timer_ids[] = {
+ { .compatible = "atmel,at91rm9200-st" },
+ { /* sentinel */ }
+};
+
+static int __init of_at91rm9200_st_init(void)
+{
+ struct device_node *np;
+ int ret;
+
+ np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+ if (!np)
+ goto err;
+
+ at91_st_base = of_iomap(np, 0);
+ if (!at91_st_base)
+ goto node_err;
+
+ /* Get the interrupts property */
+ ret = irq_of_parse_and_map(np, 0);
+ if (!ret)
+ goto ioremap_err;
+ at91rm9200_timer_irq.irq = ret;
+
+ of_node_put(np);
+
+ return 0;
+
+ioremap_err:
+ iounmap(at91_st_base);
+node_err:
+ of_node_put(np);
+err:
+ return -EINVAL;
+}
+#else
+static int __init of_at91rm9200_st_init(void)
+{
+ return -EINVAL;
+}
+#endif
+
void __init at91rm9200_ioremap_st(u32 addr)
{
+#ifdef CONFIG_OF
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+ if (np) {
+ of_node_put(np);
+ return;
+ }
+#endif
at91_st_base = ioremap(addr, 256);
if (!at91_st_base)
panic("Impossible to ioremap ST\n");
@@ -191,13 +247,16 @@ void __init at91rm9200_ioremap_st(u32 addr)
*/
void __init at91rm9200_timer_init(void)
{
+ /* For device tree enabled device: initialize here */
+ of_at91rm9200_st_init();
+
/* Disable all timer interrupts, and clear any pending ones */
at91_st_write(AT91_ST_IDR,
AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
at91_st_read(AT91_ST_SR);
/* Make IRQs happen for the system timer */
- setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
+ setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
/* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
* directly for the clocksource and all clockevents, after adjusting
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index f8202615f4a8..c9e029e44d8a 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -230,11 +230,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
CLKDEV_CON_ID("pioA", &pioA_clk),
CLKDEV_CON_ID("pioB", &pioB_clk),
CLKDEV_CON_ID("pioC", &pioC_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -390,10 +394,10 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
-struct at91_init_soc __initdata at91sam9260_soc = {
+AT91_SOC_START(sam9260)
.map_io = at91sam9260_map_io,
.default_irq_priority = at91sam9260_default_irq_priority,
.ioremap_registers = at91sam9260_ioremap_registers,
.register_clocks = at91sam9260_register_clocks,
.init = at91sam9260_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 04295c04b3e0..4d262f346fd9 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -334,10 +334,10 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
-struct at91_init_soc __initdata at91sam9261_soc = {
+AT91_SOC_START(sam9261)
.map_io = at91sam9261_map_io,
.default_irq_priority = at91sam9261_default_irq_priority,
.ioremap_registers = at91sam9261_ioremap_registers,
.register_clocks = at91sam9261_register_clocks,
.init = at91sam9261_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index d6f9c23927c4..ed390f6fa232 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -211,7 +211,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
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),
+ CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk),
};
static struct clk_lookup usart_clocks_lookups[] = {
@@ -365,10 +372,10 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller (IRQ1) */
};
-struct at91_init_soc __initdata at91sam9263_soc = {
+AT91_SOC_START(sam9263)
.map_io = at91sam9263_map_io,
.default_irq_priority = at91sam9263_default_irq_priority,
.ioremap_registers = at91sam9263_ioremap_registers,
.register_clocks = at91sam9263_register_clocks,
.init = at91sam9263_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 84af1b506d92..c5c2acc4bf22 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -256,10 +256,18 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
/* fake hclk clock */
CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk),
+
CLKDEV_CON_ID("pioA", &pioA_clk),
CLKDEV_CON_ID("pioB", &pioB_clk),
CLKDEV_CON_ID("pioC", &pioC_clk),
@@ -409,10 +417,10 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller (IRQ0) */
};
-struct at91_init_soc __initdata at91sam9g45_soc = {
+AT91_SOC_START(sam9g45)
.map_io = at91sam9g45_map_io,
.default_irq_priority = at91sam9g45_default_irq_priority,
.ioremap_registers = at91sam9g45_ioremap_registers,
.register_clocks = at91sam9g45_register_clocks,
.init = at91sam9g45_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index 732d3d3f4ec5..70b3a99244ab 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -168,13 +168,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
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("mci_clk", "f0008000.mmc", &mmc_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_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),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &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),
@@ -223,13 +224,10 @@ static void __init at91sam9n12_map_io(void)
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 = {
+AT91_SOC_START(sam9n12)
.map_io = at91sam9n12_map_io,
.register_clocks = at91sam9n12_register_clocks,
.init = at91sam9n12_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 72e908412222..cbe72e44c13f 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -338,10 +338,10 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
0, /* Advanced Interrupt Controller */
};
-struct at91_init_soc __initdata at91sam9rl_soc = {
+AT91_SOC_START(sam9rl)
.map_io = at91sam9rl_map_io,
.default_irq_priority = at91sam9rl_default_irq_priority,
.ioremap_registers = at91sam9rl_ioremap_registers,
.register_clocks = at91sam9rl_register_clocks,
.init = at91sam9rl_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index e5035380dcbc..3c729f0e2d3c 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -229,15 +229,17 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
+ CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_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),
+ CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
+ CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
/* additional fake clock for macb_hclk */
CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
@@ -313,18 +315,11 @@ static void __init at91sam9x5_map_io(void)
at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE);
}
-void __init at91sam9x5_initialize(void)
-{
- /* Register GPIO subsystem (using DT) */
- at91_gpio_init(NULL, 0);
-}
-
/* --------------------------------------------------------------------
* Interrupt initialization
* -------------------------------------------------------------------- */
-struct at91_init_soc __initdata at91sam9x5_soc = {
+AT91_SOC_START(sam9x5)
.map_io = at91sam9x5_map_io,
.register_clocks = at91sam9x5_register_clocks,
- .init = at91sam9x5_initialize,
-};
+AT91_SOC_END
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index e8f45c4e0ea8..3b6a94820fa0 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -30,8 +30,6 @@
static const struct of_device_id irq_of_match[] __initconst = {
{ .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { .compatible = "atmel,at91rm9200-gpio", .data = at91_gpio_of_irq_setup },
- { .compatible = "atmel,at91sam9x5-gpio", .data = at91_gpio_of_irq_setup },
{ /*sentinel*/ }
};
diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c
new file mode 100644
index 000000000000..5f9ce3da3fde
--- /dev/null
+++ b/arch/arm/mach-at91/board-rm9200-dt.c
@@ -0,0 +1,57 @@
+/*
+ * Setup code for AT91RM9200 Evaluation Kits with Device Tree support
+ *
+ * Copyright (C) 2011 Atmel,
+ * 2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ * 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+ { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
+ { /*sentinel*/ }
+};
+
+static void __init at91rm9200_dt_init_irq(void)
+{
+ of_irq_init(irq_of_match);
+}
+
+static void __init at91rm9200_dt_device_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *at91rm9200_dt_board_compat[] __initdata = {
+ "atmel,at91rm9200",
+ NULL
+};
+
+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
+ .timer = &at91rm9200_timer,
+ .map_io = at91_map_io,
+ .handle_irq = at91_aic_handle_irq,
+ .init_early = at91rm9200_dt_initialize,
+ .init_irq = at91rm9200_dt_init_irq,
+ .init_machine = at91rm9200_dt_device_init,
+ .dt_compat = at91rm9200_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index b62f560e6c75..fc593d615e7d 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base,
extern void __init at91rm9200_set_type(int type);
extern void __init at91_initialize(unsigned long main_clock);
extern void __init at91x40_initialize(unsigned long main_clock);
+extern void __init at91rm9200_dt_initialize(void);
extern void __init at91_dt_initialize(void);
/* Interrupts */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index be42cf0e74bd..c5d7e1e9d757 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -23,8 +23,6 @@
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
#include <asm/mach/irq.h>
@@ -33,6 +31,8 @@
#include "generic.h"
+#define MAX_NB_GPIO_PER_BANK 32
+
struct at91_gpio_chip {
struct gpio_chip chip;
struct at91_gpio_chip *next; /* Bank sharing same clock */
@@ -46,6 +46,7 @@ struct at91_gpio_chip {
#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
@@ -55,26 +56,27 @@ static int at91_gpiolib_direction_input(struct gpio_chip *chip,
unsigned offset);
static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
-#define AT91_GPIO_CHIP(name, nr_gpio) \
+#define AT91_GPIO_CHIP(name) \
{ \
.chip = { \
.label = name, \
+ .request = at91_gpiolib_request, \
.direction_input = at91_gpiolib_direction_input, \
.direction_output = at91_gpiolib_direction_output, \
.get = at91_gpiolib_get, \
.set = at91_gpiolib_set, \
.dbg_show = at91_gpiolib_dbg_show, \
.to_irq = at91_gpiolib_to_irq, \
- .ngpio = nr_gpio, \
+ .ngpio = MAX_NB_GPIO_PER_BANK, \
}, \
}
static struct at91_gpio_chip gpio_chip[] = {
- AT91_GPIO_CHIP("pioA", 32),
- AT91_GPIO_CHIP("pioB", 32),
- AT91_GPIO_CHIP("pioC", 32),
- AT91_GPIO_CHIP("pioD", 32),
- AT91_GPIO_CHIP("pioE", 32),
+ AT91_GPIO_CHIP("pioA"),
+ AT91_GPIO_CHIP("pioB"),
+ AT91_GPIO_CHIP("pioC"),
+ AT91_GPIO_CHIP("pioD"),
+ AT91_GPIO_CHIP("pioE"),
};
static int gpio_banks;
@@ -89,7 +91,7 @@ static unsigned long at91_gpio_caps;
static inline void __iomem *pin_to_controller(unsigned pin)
{
- pin /= 32;
+ pin /= MAX_NB_GPIO_PER_BANK;
if (likely(pin < gpio_banks))
return gpio_chip[pin].regbase;
@@ -98,7 +100,7 @@ static inline void __iomem *pin_to_controller(unsigned pin)
static inline unsigned pin_to_mask(unsigned pin)
{
- return 1 << (pin % 32);
+ return 1 << (pin % MAX_NB_GPIO_PER_BANK);
}
@@ -713,80 +715,6 @@ postcore_initcall(at91_gpio_debugfs_init);
*/
static struct lock_class_key gpio_lock_class;
-#if defined(CONFIG_OF)
-static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct at91_gpio_chip *at91_gpio = h->host_data;
-
- irq_set_lockdep_class(virq, &gpio_lock_class);
-
- /*
- * Can use the "simple" and not "edge" handler since it's
- * shorter, and the AIC handles interrupts sanely.
- */
- irq_set_chip_and_handler(virq, &gpio_irqchip,
- handle_simple_irq);
- set_irq_flags(virq, IRQF_VALID);
- irq_set_chip_data(virq, at91_gpio);
-
- return 0;
-}
-
-static struct irq_domain_ops at91_gpio_ops = {
- .map = at91_gpio_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-int __init at91_gpio_of_irq_setup(struct device_node *node,
- struct device_node *parent)
-{
- struct at91_gpio_chip *prev = NULL;
- int alias_idx = of_alias_get_id(node, "gpio");
- struct at91_gpio_chip *at91_gpio = &gpio_chip[alias_idx];
-
- /* Setup proper .irq_set_type function */
- if (has_pio3())
- gpio_irqchip.irq_set_type = alt_gpio_irq_type;
- else
- gpio_irqchip.irq_set_type = gpio_irq_type;
-
- /* Disable irqs of this PIO controller */
- __raw_writel(~0, at91_gpio->regbase + PIO_IDR);
-
- /* Setup irq domain */
- at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
- &at91_gpio_ops, at91_gpio);
- if (!at91_gpio->domain)
- panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
- at91_gpio->pioc_idx);
-
- /* Setup chained handler */
- if (at91_gpio->pioc_idx)
- prev = &gpio_chip[at91_gpio->pioc_idx - 1];
-
- /* The toplevel handler handles one bank of GPIOs, except
- * on some SoC it can handles up to three...
- * We only set up the handler for the first of the list.
- */
- if (prev && prev->next == at91_gpio)
- return 0;
-
- at91_gpio->pioc_virq = irq_create_mapping(irq_find_host(parent),
- at91_gpio->pioc_hwirq);
- irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
- irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
-
- return 0;
-}
-#else
-int __init at91_gpio_of_irq_setup(struct device_node *node,
- struct device_node *parent)
-{
- return -EINVAL;
-}
-#endif
-
/*
* irqdomain initialization: pile up irqdomains on top of AIC range
*/
@@ -862,6 +790,16 @@ void __init at91_gpio_irq_setup(void)
}
/* gpiolib support */
+static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << offset;
+
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+
static int at91_gpiolib_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@@ -975,81 +913,11 @@ err:
return -EINVAL;
}
-#ifdef CONFIG_OF_GPIO
-static void __init of_at91_gpio_init_one(struct device_node *np)
-{
- int alias_idx;
- struct at91_gpio_chip *at91_gpio;
-
- if (!np)
- return;
-
- alias_idx = of_alias_get_id(np, "gpio");
- if (alias_idx >= MAX_GPIO_BANKS) {
- pr_err("at91_gpio, failed alias idx(%d) > MAX_GPIO_BANKS(%d), ignoring.\n",
- alias_idx, MAX_GPIO_BANKS);
- return;
- }
-
- at91_gpio = &gpio_chip[alias_idx];
- at91_gpio->chip.base = alias_idx * at91_gpio->chip.ngpio;
-
- at91_gpio->regbase = of_iomap(np, 0);
- if (!at91_gpio->regbase) {
- pr_err("at91_gpio.%d, failed to map registers, ignoring.\n",
- alias_idx);
- return;
- }
-
- /* Get the interrupts property */
- if (of_property_read_u32(np, "interrupts", &at91_gpio->pioc_hwirq)) {
- pr_err("at91_gpio.%d, failed to get interrupts property, ignoring.\n",
- alias_idx);
- goto ioremap_err;
- }
-
- /* Get capabilities from compatibility property */
- if (of_device_is_compatible(np, "atmel,at91sam9x5-gpio"))
- at91_gpio_caps |= AT91_GPIO_CAP_PIO3;
-
- /* Setup clock */
- if (at91_gpio_setup_clk(alias_idx))
- goto ioremap_err;
-
- at91_gpio->chip.of_node = np;
- gpio_banks = max(gpio_banks, alias_idx + 1);
- at91_gpio->pioc_idx = alias_idx;
- return;
-
-ioremap_err:
- iounmap(at91_gpio->regbase);
-}
-
-static int __init of_at91_gpio_init(void)
-{
- struct device_node *np = NULL;
-
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- for_each_compatible_node(np, NULL, "atmel,at91rm9200-gpio")
- of_at91_gpio_init_one(np);
-
- return gpio_banks > 0 ? 0 : -EINVAL;
-}
-#else
-static int __init of_at91_gpio_init(void)
-{
- return -EINVAL;
-}
-#endif
-
static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
{
struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
- at91_gpio->chip.base = idx * at91_gpio->chip.ngpio;
+ at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK;
at91_gpio->pioc_hwirq = pioc_hwirq;
at91_gpio->pioc_idx = idx;
@@ -1079,11 +947,11 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
BUG_ON(nr_banks > MAX_GPIO_BANKS);
- if (of_at91_gpio_init() < 0) {
- /* No GPIO controller found in device tree */
- for (i = 0; i < nr_banks; i++)
- at91_gpio_init_one(i, data[i].regbase, data[i].id);
- }
+ if (of_have_populated_dt())
+ return;
+
+ for (i = 0; i < nr_banks; i++)
+ at91_gpio_init_one(i, data[i].regbase, data[i].id);
for (i = 0; i < gpio_banks; i++) {
at91_gpio = &gpio_chip[i];
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index c55a4364ffb4..a0d92a960f46 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -70,16 +70,6 @@ struct at91_cf_data {
extern void __init at91_add_device_cf(struct at91_cf_data *data);
/* MMC / SD */
- /* at91_mci platform config */
-struct at91_mmc_data {
- int det_pin; /* card detect IRQ */
- unsigned slot_b:1; /* uses Slot B */
- unsigned wire4:1; /* (SD) supports DAT0..DAT3 */
- int wp_pin; /* (SD) writeprotect detect */
- int vcc_pin; /* power switching (high == on) */
-};
-extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
-
/* atmel-mci platform config */
extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 0b32c81730a5..19cdd0b5b391 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
#include <asm/system_misc.h>
#include <asm/mach/map.h>
@@ -338,6 +339,7 @@ static void at91_dt_rstc(void)
}
static struct of_device_id ramc_ids[] = {
+ { .compatible = "atmel,at91rm9200-sdramc" },
{ .compatible = "atmel,at91sam9260-sdramc" },
{ .compatible = "atmel,at91sam9g45-ddramc" },
{ /*sentinel*/ }
@@ -436,6 +438,19 @@ end:
of_node_put(np);
}
+void __init at91rm9200_dt_initialize(void)
+{
+ at91_dt_ramc();
+
+ /* Init clock subsystem */
+ at91_dt_clock_init();
+
+ /* Register the processor-specific clocks */
+ at91_boot_soc.register_clocks();
+
+ at91_boot_soc.init();
+}
+
void __init at91_dt_initialize(void)
{
at91_dt_rstc();
@@ -448,7 +463,8 @@ void __init at91_dt_initialize(void)
/* Register the processor-specific clocks */
at91_boot_soc.register_clocks();
- at91_boot_soc.init();
+ if (at91_boot_soc.init)
+ at91_boot_soc.init();
}
#endif
@@ -463,4 +479,6 @@ void __init at91_initialize(unsigned long main_clock)
at91_boot_soc.register_clocks();
at91_boot_soc.init();
+
+ pinctrl_provide_dummies();
}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
index a9cfeb153719..9c6d3d4f9a23 100644
--- a/arch/arm/mach-at91/soc.h
+++ b/arch/arm/mach-at91/soc.h
@@ -5,6 +5,7 @@
*/
struct at91_init_soc {
+ int builtin;
unsigned int *default_irq_priority;
void (*map_io)(void);
void (*ioremap_registers)(void);
@@ -22,9 +23,18 @@ extern struct at91_init_soc at91sam9rl_soc;
extern struct at91_init_soc at91sam9x5_soc;
extern struct at91_init_soc at91sam9n12_soc;
+#define AT91_SOC_START(_name) \
+struct at91_init_soc __initdata at91##_name##_soc \
+ __used \
+ = { \
+ .builtin = 1, \
+
+#define AT91_SOC_END \
+};
+
static inline int at91_soc_is_enabled(void)
{
- return at91_boot_soc.init != NULL;
+ return at91_boot_soc.builtin;
}
#if !defined(CONFIG_SOC_AT91RM9200)
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index cd0c8b1e1ecf..14e9947bad6e 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
break;
case VPBE_ENC_CUSTOM_TIMINGS:
if (pclock <= 27000000) {
- v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
- DM644X_VPSS_DACCLKEN;
+ v |= DM644X_VPSS_DACCLKEN;
writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
} else {
/*
diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h
index 7bcd0dfce4b1..b47f75038686 100644
--- a/arch/arm/mach-dove/include/mach/pm.h
+++ b/arch/arm/mach-dove/include/mach/pm.h
@@ -63,7 +63,7 @@ static inline int pmu_to_irq(int pin)
static inline int irq_to_pmu(int irq)
{
- if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS)
+ if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS)
return irq - IRQ_DOVE_PMU_START;
return -EINVAL;
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index 087711524e8a..bc4344aa1009 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -46,8 +46,20 @@ static void pmu_irq_ack(struct irq_data *d)
int pin = irq_to_pmu(d->irq);
u32 u;
+ /*
+ * The PMU mask register is not RW0C: it is RW. This means that
+ * the bits take whatever value is written to them; if you write
+ * a '1', you will set the interrupt.
+ *
+ * Unfortunately this means there is NO race free way to clear
+ * these interrupts.
+ *
+ * So, let's structure the code so that the window is as small as
+ * possible.
+ */
u = ~(1 << (pin & 31));
- writel(u, PMU_INTERRUPT_CAUSE);
+ u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
+ writel_relaxed(u, PMU_INTERRUPT_CAUSE);
}
static struct irq_chip pmu_irq_chip = {
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index 21d568b3b149..87e07d6fc615 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -275,6 +275,9 @@ static int __init exynos_dma_init(void)
exynos_pdma1_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4210_pdma1_peri);
exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+
+ if (samsung_rev() == EXYNOS4210_REV_0)
+ exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1;
} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
exynos_pdma0_pdata.nr_valid_peri =
ARRAY_SIZE(exynos4212_pdma0_peri);
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 8480849affb9..ed4da4544cd2 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -90,6 +90,7 @@
#define EXYNOS4_PA_MDMA0 0x10810000
#define EXYNOS4_PA_MDMA1 0x12850000
+#define EXYNOS4_PA_S_MDMA1 0x12840000
#define EXYNOS4_PA_PDMA0 0x12680000
#define EXYNOS4_PA_PDMA1 0x12690000
#define EXYNOS5_PA_MDMA0 0x10800000
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index e428f3ab15c7..b3d86d7081a0 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -21,10 +21,9 @@
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
#include <linux/slab.h>
-#include <linux/clkdev.h>
-#include <asm/hardware/icst.h>
#include <mach/lm.h>
#include <mach/impd1.h>
#include <asm/sizes.h>
@@ -36,45 +35,6 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
struct impd1_module {
void __iomem *base;
- struct clk vcos[2];
- struct clk_lookup *clks[3];
-};
-
-static const struct icst_params impd1_vco_params = {
- .ref = 24000000, /* 24 MHz */
- .vco_max = ICST525_VCO_MAX_3V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 12,
- .vd_max = 519,
- .rd_min = 3,
- .rd_max = 120,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-static void impd1_setvco(struct clk *clk, struct icst_vco vco)
-{
- struct impd1_module *impd1 = clk->data;
- u32 val = vco.v | (vco.r << 9) | (vco.s << 16);
-
- writel(0xa05f, impd1->base + IMPD1_LOCK);
- writel(val, clk->vcoreg);
- writel(0, impd1->base + IMPD1_LOCK);
-
-#ifdef DEBUG
- vco.v = val & 0x1ff;
- vco.r = (val >> 9) & 0x7f;
- vco.s = (val >> 16) & 7;
-
- pr_debug("IM-PD1: VCO%d clock is %ld Hz\n",
- vconr, icst525_hz(&impd1_vco_params, vco));
-#endif
-}
-
-static const struct clk_ops impd1_clk_ops = {
- .round = icst_clk_round,
- .set = icst_clk_set,
- .setvco = impd1_setvco,
};
void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -344,10 +304,6 @@ static struct impd1_device impd1_devs[] = {
}
};
-static struct clk fixed_14745600 = {
- .rate = 14745600,
-};
-
static int impd1_probe(struct lm_device *dev)
{
struct impd1_module *impd1;
@@ -376,23 +332,7 @@ static int impd1_probe(struct lm_device *dev)
printk("IM-PD1 found at 0x%08lx\n",
(unsigned long)dev->resource.start);
- for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
- impd1->vcos[i].ops = &impd1_clk_ops,
- impd1->vcos[i].owner = THIS_MODULE,
- impd1->vcos[i].params = &impd1_vco_params,
- impd1->vcos[i].data = impd1;
- }
- impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1;
- impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2;
-
- impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000",
- dev->id);
- impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100",
- dev->id);
- impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200",
- dev->id);
- for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
- clkdev_add(impd1->clks[i]);
+ integrator_impd1_clk_init(impd1->base, dev->id);
for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
struct impd1_device *idev = impd1_devs + i;
@@ -431,12 +371,9 @@ static int impd1_remove_one(struct device *dev, void *data)
static void impd1_remove(struct lm_device *dev)
{
struct impd1_module *impd1 = lm_get_drvdata(dev);
- int i;
device_for_each_child(&dev->dev, NULL, impd1_remove_one);
-
- for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
- clkdev_drop(impd1->clks[i]);
+ integrator_impd1_clk_exit(dev->id);
lm_set_drvdata(dev, NULL);
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 1694f01ce2b6..6d6bde3e15fa 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -410,6 +410,7 @@ void __init ixp4xx_pci_preinit(void)
* Enable the IO window to be way up high, at 0xfffffc00
*/
local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
+ local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
} else {
printk("PCI: IXP4xx is target - No bus scan performed\n");
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index fdf91a160884..8c0c0e2d0727 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -67,15 +67,12 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
.length = IXP4XX_PCI_CFG_REGION_SIZE,
.type = MT_DEVICE
- },
-#ifdef CONFIG_DEBUG_LL
- { /* Debug UART mapping */
- .virtual = (unsigned long)IXP4XX_DEBUG_UART_BASE_VIRT,
- .pfn = __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
- .length = IXP4XX_DEBUG_UART_REGION_SIZE,
+ }, { /* Queue Manager */
+ .virtual = (unsigned long)IXP4XX_QMGR_BASE_VIRT,
+ .pfn = __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
+ .length = IXP4XX_QMGR_REGION_SIZE,
.type = MT_DEVICE
- }
-#endif
+ },
};
void __init ixp4xx_map_io(void)
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index b800a031207c..53b8348dfcc2 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -15,6 +15,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/pci.h>
+#include <asm/system_info.h>
#define SLOT_ETHA 0x0B /* IDSEL = AD21 */
#define SLOT_ETHB 0x0C /* IDSEL = AD20 */
@@ -329,7 +330,7 @@ static struct platform_device device_hss_tab[] = {
};
-static struct platform_device *device_tab[6] __initdata = {
+static struct platform_device *device_tab[7] __initdata = {
&device_flash, /* index 0 */
};
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index 8c9f8d564492..ff686cbc5df4 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -17,8 +17,8 @@
#else
mov \rp, #0
#endif
- orr \rv, \rp, #0xff000000 @ virtual
- orr \rv, \rv, #0x00b00000
+ orr \rv, \rp, #0xfe000000 @ virtual
+ orr \rv, \rv, #0x00f00000
orr \rp, \rp, #0xc8000000 @ physical
.endm
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
index eb68b61ce975..c5bae9c035d5 100644
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -30,51 +30,43 @@
*
* 0x50000000 0x10000000 ioremap'd EXP BUS
*
- * 0x6000000 0x00004000 ioremap'd QMgr
+ * 0xC8000000 0x00013000 0xFEF00000 On-Chip Peripherals
*
- * 0xC0000000 0x00001000 0xffbff000 PCI CFG
+ * 0xC0000000 0x00001000 0xFEF13000 PCI CFG
*
- * 0xC4000000 0x00001000 0xffbfe000 EXP CFG
+ * 0xC4000000 0x00001000 0xFEF14000 EXP CFG
*
- * 0xC8000000 0x00013000 0xffbeb000 On-Chip Peripherals
+ * 0x60000000 0x00004000 0xFEF15000 QMgr
*/
/*
* Queue Manager
*/
-#define IXP4XX_QMGR_BASE_PHYS (0x60000000)
-#define IXP4XX_QMGR_REGION_SIZE (0x00004000)
+#define IXP4XX_QMGR_BASE_PHYS 0x60000000
+#define IXP4XX_QMGR_BASE_VIRT IOMEM(0xFEF15000)
+#define IXP4XX_QMGR_REGION_SIZE 0x00004000
/*
- * Expansion BUS Configuration registers
+ * Peripheral space, including debug UART. Must be section-aligned so that
+ * it can be used with the low-level debug code.
*/
-#define IXP4XX_EXP_CFG_BASE_PHYS (0xC4000000)
-#define IXP4XX_EXP_CFG_BASE_VIRT IOMEM(0xFFBFE000)
-#define IXP4XX_EXP_CFG_REGION_SIZE (0x00001000)
+#define IXP4XX_PERIPHERAL_BASE_PHYS 0xC8000000
+#define IXP4XX_PERIPHERAL_BASE_VIRT IOMEM(0xFEF00000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE 0x00013000
/*
* PCI Config registers
*/
-#define IXP4XX_PCI_CFG_BASE_PHYS (0xC0000000)
-#define IXP4XX_PCI_CFG_BASE_VIRT IOMEM(0xFFBFF000)
-#define IXP4XX_PCI_CFG_REGION_SIZE (0x00001000)
-
-/*
- * Peripheral space
- */
-#define IXP4XX_PERIPHERAL_BASE_PHYS (0xC8000000)
-#define IXP4XX_PERIPHERAL_BASE_VIRT IOMEM(0xFFBEB000)
-#define IXP4XX_PERIPHERAL_REGION_SIZE (0x00013000)
+#define IXP4XX_PCI_CFG_BASE_PHYS 0xC0000000
+#define IXP4XX_PCI_CFG_BASE_VIRT IOMEM(0xFEF13000)
+#define IXP4XX_PCI_CFG_REGION_SIZE 0x00001000
/*
- * Debug UART
- *
- * This is basically a remap of UART1 into a region that is section
- * aligned so that it * can be used with the low-level debug code.
+ * Expansion BUS Configuration registers
*/
-#define IXP4XX_DEBUG_UART_BASE_PHYS (0xC8000000)
-#define IXP4XX_DEBUG_UART_BASE_VIRT IOMEM(0xffb00000)
-#define IXP4XX_DEBUG_UART_REGION_SIZE (0x00001000)
+#define IXP4XX_EXP_CFG_BASE_PHYS 0xC4000000
+#define IXP4XX_EXP_CFG_BASE_VIRT 0xFEF14000
+#define IXP4XX_EXP_CFG_REGION_SIZE 0x00001000
#define IXP4XX_EXP_CS0_OFFSET 0x00
#define IXP4XX_EXP_CS1_OFFSET 0x04
diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
index 9e7cad2d54cb..4de8da536dbb 100644
--- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h
+++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
@@ -86,7 +86,7 @@ void qmgr_release_queue(unsigned int queue);
static inline void qmgr_put_entry(unsigned int queue, u32 val)
{
- extern struct qmgr_regs __iomem *qmgr_regs;
+ struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
#if DEBUG_QMGR
BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
@@ -99,7 +99,7 @@ static inline void qmgr_put_entry(unsigned int queue, u32 val)
static inline u32 qmgr_get_entry(unsigned int queue)
{
u32 val;
- extern struct qmgr_regs __iomem *qmgr_regs;
+ const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
val = __raw_readl(&qmgr_regs->acc[queue][0]);
#if DEBUG_QMGR
BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
@@ -112,14 +112,14 @@ static inline u32 qmgr_get_entry(unsigned int queue)
static inline int __qmgr_get_stat1(unsigned int queue)
{
- extern struct qmgr_regs __iomem *qmgr_regs;
+ const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
>> ((queue & 7) << 2)) & 0xF;
}
static inline int __qmgr_get_stat2(unsigned int queue)
{
- extern struct qmgr_regs __iomem *qmgr_regs;
+ const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
BUG_ON(queue >= HALF_QUEUES);
return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
>> ((queue & 0xF) << 1)) & 0x3;
@@ -145,7 +145,7 @@ static inline int qmgr_stat_empty(unsigned int queue)
*/
static inline int qmgr_stat_below_low_watermark(unsigned int queue)
{
- extern struct qmgr_regs __iomem *qmgr_regs;
+ const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
if (queue >= HALF_QUEUES)
return (__raw_readl(&qmgr_regs->statne_h) >>
(queue - HALF_QUEUES)) & 0x01;
@@ -172,7 +172,7 @@ static inline int qmgr_stat_above_high_watermark(unsigned int queue)
*/
static inline int qmgr_stat_full(unsigned int queue)
{
- extern struct qmgr_regs __iomem *qmgr_regs;
+ const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
if (queue >= HALF_QUEUES)
return (__raw_readl(&qmgr_regs->statf_h) >>
(queue - HALF_QUEUES)) & 0x01;
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index a17ed79207a4..d4eb09a62863 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -116,7 +116,11 @@
/* NPE mailbox_status value for reset */
#define RESET_MBOX_STAT 0x0000F0F0
-const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
#define print_npe(pri, npe, fmt, ...) \
printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
@@ -724,6 +728,9 @@ module_exit(npe_cleanup_module);
MODULE_AUTHOR("Krzysztof Halasa");
MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
EXPORT_SYMBOL(npe_names);
EXPORT_SYMBOL(npe_running);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index 852f7c9f87d0..9d1b6b7c394c 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <mach/qmgr.h>
-struct qmgr_regs __iomem *qmgr_regs;
+static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
static struct resource *mem_res;
static spinlock_t qmgr_lock;
static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
@@ -293,12 +293,6 @@ static int qmgr_init(void)
if (mem_res == NULL)
return -EBUSY;
- qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
- if (qmgr_regs == NULL) {
- err = -ENOMEM;
- goto error_map;
- }
-
/* reset qmgr registers */
for (i = 0; i < 4; i++) {
__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
@@ -347,8 +341,6 @@ static int qmgr_init(void)
error_irq2:
free_irq(IRQ_IXP4XX_QM1, NULL);
error_irq:
- iounmap(qmgr_regs);
-error_map:
release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
return err;
}
@@ -359,7 +351,6 @@ static void qmgr_remove(void)
free_irq(IRQ_IXP4XX_QM2, NULL);
synchronize_irq(IRQ_IXP4XX_QM1);
synchronize_irq(IRQ_IXP4XX_QM2);
- iounmap(qmgr_regs);
release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
}
@@ -369,7 +360,6 @@ module_exit(qmgr_remove);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Krzysztof Halasa");
-EXPORT_SYMBOL(qmgr_regs);
EXPORT_SYMBOL(qmgr_set_irq);
EXPORT_SYMBOL(qmgr_enable_irq);
EXPORT_SYMBOL(qmgr_disable_irq);
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index ec544918b12c..74fc5a074fc4 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -207,14 +207,19 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}
+/*
+ * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
+ * is operating as a root complex this needs to be switched to
+ * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
+ * the device. Decoding setup is handled by the orion code.
+ */
static void __devinit rc_pci_fixup(struct pci_dev *dev)
{
- /*
- * Prevent enumeration of root complex.
- */
if (dev->bus->parent == NULL && dev->devfn == 0) {
int i;
+ dev->class &= 0xff;
+ dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
dev->resource[i].start = 0;
dev->resource[i].end = 0;
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index bfa1eab91f41..22ef8a1abe08 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -24,6 +24,7 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <asm/hardware/vic.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>
@@ -32,9 +33,7 @@
#include <asm/mach/flash.h>
#include <asm/mach/time.h>
-#include <plat/gpio-nomadik.h>
#include <plat/mtu.h>
-#include <plat/pincfg.h>
#include <linux/platform_data/mtd-nomadik-nand.h>
#include <mach/fsmc.h>
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index b617eaed0ce5..1273931303fb 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -26,8 +26,8 @@
#include <linux/irq.h>
#include <linux/dma-mapping.h>
#include <linux/platform_data/clk-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
-#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c
index 6d14454d4609..0c2f6628299a 100644
--- a/arch/arm/mach-nomadik/i2c-8815nhk.c
+++ b/arch/arm/mach-nomadik/i2c-8815nhk.c
@@ -4,8 +4,7 @@
#include <linux/i2c-algo-bit.h>
#include <linux/i2c-gpio.h>
#include <linux/platform_device.h>
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
/*
* There are two busses in the 8815NHK.
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 48d5e41dfbfa..378590694447 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void)
} else
return;
+ /* Make sure that the GPIO pins are muxed correctly */
+ omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
+
err = gpio_request_array(igep_wlan_bt_gpios,
ARRAY_SIZE(igep_wlan_bt_gpios));
if (err) {
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 48daac2581b4..84551f205e46 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
struct spi_board_info *spi_bi = &ads7846_spi_board_info;
int err;
- err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
- if (err) {
- pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
- return;
- }
+ /*
+ * If a board defines get_pendown_state() function, request the pendown
+ * GPIO and set the GPIO debounce time.
+ * If a board does not define the get_pendown_state() function, then
+ * the ads7846 driver will setup the pendown GPIO itself.
+ */
+ if (board_pdata && board_pdata->get_pendown_state) {
+ err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+ if (err) {
+ pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+ return;
+ }
- if (gpio_debounce)
- gpio_set_debounce(gpio_pendown, gpio_debounce);
+ if (gpio_debounce)
+ gpio_set_debounce(gpio_pendown, gpio_debounce);
+
+ gpio_export(gpio_pendown, 0);
+ }
spi_bi->bus_num = bus_num;
spi_bi->irq = gpio_to_irq(gpio_pendown);
+ ads7846_config.gpio_pendown = gpio_pendown;
+
if (board_pdata) {
board_pdata->gpio_pendown = gpio_pendown;
+ board_pdata->gpio_pendown_debounce = gpio_debounce;
spi_bi->platform_data = board_pdata;
- if (board_pdata->get_pendown_state)
- gpio_export(gpio_pendown, 0);
- } else {
- ads7846_config.gpio_pendown = gpio_pendown;
}
- if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
- gpio_free(gpio_pendown);
-
spi_register_board_info(&ads7846_spi_board_info, 1);
}
#else
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 44c42057b61c..a256135d8e48 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type,
{
/* PMIC part*/
omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
+ omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data);
/* Register additional devices on i2c1 bus if needed */
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 0a43f3189c21..7a05de794a8c 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -548,7 +548,6 @@ static struct platform_device fsi_ak4648_device = {
/* I2C */
static struct pcf857x_platform_data pcf8575_pdata = {
.gpio_base = GPIO_PCF8575_BASE,
- .irq = intcs_evt2irq(0x3260), /* IRQ19 */
};
static struct i2c_board_info i2c0_devices[] = {
@@ -570,6 +569,7 @@ static struct i2c_board_info i2c1_devices[] = {
static struct i2c_board_info i2c3_devices[] = {
{
I2C_BOARD_INFO("pcf8575", 0x20),
+ .irq = intcs_evt2irq(0x3260), /* IRQ19 */
.platform_data = &pcf8575_pdata,
},
};
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index b8efac4daed8..ece8a2dfb814 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1445,8 +1445,6 @@ static struct platform_device pinctrl_device = {
static struct u300_gpio_platform u300_gpio_plat = {
.ports = 7,
.gpio_base = 0,
- .gpio_irq_base = IRQ_U300_GPIO_BASE,
- .pinctrl_device = &pinctrl_device,
};
static struct platform_device gpio_device = {
@@ -1590,6 +1588,7 @@ static struct platform_device *platform_devs[] __initdata = {
&i2c1_device,
&keypad_device,
&rtc_device,
+ &pinctrl_device,
&gpio_device,
&nand_device,
&wdog_device,
@@ -1804,7 +1803,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
.atag_offset = 0x100,
.map_io = u300_map_io,
- .nr_irqs = NR_IRQS_U300,
+ .nr_irqs = 0,
.init_irq = u300_init_irq,
.handle_irq = vic_handle_irq,
.timer = &u300_timer,
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
index e27425a63fa1..21d5e76a6cd3 100644
--- a/arch/arm/mach-u300/include/mach/irqs.h
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -12,79 +12,69 @@
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
-#define IRQ_U300_INTCON0_START 1
-#define IRQ_U300_INTCON1_START 33
+#define IRQ_U300_INTCON0_START 32
+#define IRQ_U300_INTCON1_START 64
/* These are on INTCON0 - 30 lines */
-#define IRQ_U300_IRQ0_EXT 1
-#define IRQ_U300_IRQ1_EXT 2
-#define IRQ_U300_DMA 3
-#define IRQ_U300_VIDEO_ENC_0 4
-#define IRQ_U300_VIDEO_ENC_1 5
-#define IRQ_U300_AAIF_RX 6
-#define IRQ_U300_AAIF_TX 7
-#define IRQ_U300_AAIF_VGPIO 8
-#define IRQ_U300_AAIF_WAKEUP 9
-#define IRQ_U300_PCM_I2S0_FRAME 10
-#define IRQ_U300_PCM_I2S0_FIFO 11
-#define IRQ_U300_PCM_I2S1_FRAME 12
-#define IRQ_U300_PCM_I2S1_FIFO 13
-#define IRQ_U300_XGAM_GAMCON 14
-#define IRQ_U300_XGAM_CDI 15
-#define IRQ_U300_XGAM_CDICON 16
-#define IRQ_U300_XGAM_PDI 18
-#define IRQ_U300_XGAM_PDICON 19
-#define IRQ_U300_XGAM_GAMEACC 20
-#define IRQ_U300_XGAM_MCIDCT 21
-#define IRQ_U300_APEX 22
-#define IRQ_U300_UART0 23
-#define IRQ_U300_SPI 24
-#define IRQ_U300_TIMER_APP_OS 25
-#define IRQ_U300_TIMER_APP_DD 26
-#define IRQ_U300_TIMER_APP_GP1 27
-#define IRQ_U300_TIMER_APP_GP2 28
-#define IRQ_U300_TIMER_OS 29
-#define IRQ_U300_TIMER_MS 30
-#define IRQ_U300_KEYPAD_KEYBF 31
-#define IRQ_U300_KEYPAD_KEYBR 32
+#define IRQ_U300_IRQ0_EXT 32
+#define IRQ_U300_IRQ1_EXT 33
+#define IRQ_U300_DMA 34
+#define IRQ_U300_VIDEO_ENC_0 35
+#define IRQ_U300_VIDEO_ENC_1 36
+#define IRQ_U300_AAIF_RX 37
+#define IRQ_U300_AAIF_TX 38
+#define IRQ_U300_AAIF_VGPIO 39
+#define IRQ_U300_AAIF_WAKEUP 40
+#define IRQ_U300_PCM_I2S0_FRAME 41
+#define IRQ_U300_PCM_I2S0_FIFO 42
+#define IRQ_U300_PCM_I2S1_FRAME 43
+#define IRQ_U300_PCM_I2S1_FIFO 44
+#define IRQ_U300_XGAM_GAMCON 45
+#define IRQ_U300_XGAM_CDI 46
+#define IRQ_U300_XGAM_CDICON 47
+#define IRQ_U300_XGAM_PDI 49
+#define IRQ_U300_XGAM_PDICON 50
+#define IRQ_U300_XGAM_GAMEACC 51
+#define IRQ_U300_XGAM_MCIDCT 52
+#define IRQ_U300_APEX 53
+#define IRQ_U300_UART0 54
+#define IRQ_U300_SPI 55
+#define IRQ_U300_TIMER_APP_OS 56
+#define IRQ_U300_TIMER_APP_DD 57
+#define IRQ_U300_TIMER_APP_GP1 58
+#define IRQ_U300_TIMER_APP_GP2 59
+#define IRQ_U300_TIMER_OS 60
+#define IRQ_U300_TIMER_MS 61
+#define IRQ_U300_KEYPAD_KEYBF 62
+#define IRQ_U300_KEYPAD_KEYBR 63
/* These are on INTCON1 - 32 lines */
-#define IRQ_U300_GPIO_PORT0 33
-#define IRQ_U300_GPIO_PORT1 34
-#define IRQ_U300_GPIO_PORT2 35
+#define IRQ_U300_GPIO_PORT0 64
+#define IRQ_U300_GPIO_PORT1 65
+#define IRQ_U300_GPIO_PORT2 66
/* These are for DB3150, DB3200 and DB3350 */
-#define IRQ_U300_WDOG 36
-#define IRQ_U300_EVHIST 37
-#define IRQ_U300_MSPRO 38
-#define IRQ_U300_MMCSD_MCIINTR0 39
-#define IRQ_U300_MMCSD_MCIINTR1 40
-#define IRQ_U300_I2C0 41
-#define IRQ_U300_I2C1 42
-#define IRQ_U300_RTC 43
-#define IRQ_U300_NFIF 44
-#define IRQ_U300_NFIF2 45
+#define IRQ_U300_WDOG 67
+#define IRQ_U300_EVHIST 68
+#define IRQ_U300_MSPRO 69
+#define IRQ_U300_MMCSD_MCIINTR0 70
+#define IRQ_U300_MMCSD_MCIINTR1 71
+#define IRQ_U300_I2C0 72
+#define IRQ_U300_I2C1 73
+#define IRQ_U300_RTC 74
+#define IRQ_U300_NFIF 75
+#define IRQ_U300_NFIF2 76
/* The DB3350-specific interrupt lines */
-#define IRQ_U300_ISP_F0 46
-#define IRQ_U300_ISP_F1 47
-#define IRQ_U300_ISP_F2 48
-#define IRQ_U300_ISP_F3 49
-#define IRQ_U300_ISP_F4 50
-#define IRQ_U300_GPIO_PORT3 51
-#define IRQ_U300_SYSCON_PLL_LOCK 52
-#define IRQ_U300_UART1 53
-#define IRQ_U300_GPIO_PORT4 54
-#define IRQ_U300_GPIO_PORT5 55
-#define IRQ_U300_GPIO_PORT6 56
-#define U300_VIC_IRQS_END 57
-
-/* Maximum 8*7 GPIO lines */
-#ifdef CONFIG_PINCTRL_COH901
-#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END)
-#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56)
-#else
-#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END)
-#endif
-
-#define NR_IRQS_U300 (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
+#define IRQ_U300_ISP_F0 77
+#define IRQ_U300_ISP_F1 78
+#define IRQ_U300_ISP_F2 79
+#define IRQ_U300_ISP_F3 80
+#define IRQ_U300_ISP_F4 81
+#define IRQ_U300_GPIO_PORT3 82
+#define IRQ_U300_SYSCON_PLL_LOCK 83
+#define IRQ_U300_UART1 84
+#define IRQ_U300_GPIO_PORT4 85
+#define IRQ_U300_GPIO_PORT5 86
+#define IRQ_U300_GPIO_PORT6 87
+#define U300_VIC_IRQS_END 88
#endif
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index 070629a95625..33631c9f1218 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -7,9 +7,8 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/gpio.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
#include <plat/ste_dma40.h>
#include <mach/devices.h>
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index a267c6d30e37..c34d4efd0d5c 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -9,10 +9,9 @@
#include <linux/bug.h>
#include <linux/string.h>
#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <asm/mach-types.h>
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 416d436111f2..0a3dd601a400 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -37,13 +37,13 @@
#include <linux/of_platform.h>
#include <linux/leds.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <plat/ste_dma40.h>
-#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index bcdfe6b1d453..91f028c1264a 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,14 +17,14 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mfd/abx500/ab8500.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <asm/pmu.h>
#include <asm/mach/map.h>
-#include <plat/gpio-nomadik.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
-#include <linux/platform_data/usb-musb-ux500.h>
#include <mach/db8500-regs.h>
#include "devices-db8500.h"
@@ -158,7 +158,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");
+ dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE);
}
static int usb_db8500_rx_dma_cfg[] = {
@@ -214,9 +214,6 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
db8500_add_gpios(parent);
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
- 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;
@@ -236,9 +233,6 @@ struct device * __init u8500_of_init_devices(void)
db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
- platform_device_register_data(parent,
- "cpufreq-u8500", -1, NULL, 0);
-
u8500_dma40_device.dev.parent = parent;
/*
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index dfdd4a54668d..692a77a1c153 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -11,8 +11,7 @@
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
-
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
index 7fbf0ba336e1..96fa4ac89e2e 100644
--- a/arch/arm/mach-ux500/devices-common.h
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -129,12 +129,18 @@ 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)
+dbx500_add_pinctrl(struct device *parent, const char *name,
+ resource_size_t base)
{
+ struct resource res[] = {
+ DEFINE_RES_MEM(base, SZ_8K),
+ };
struct platform_device_info pdevinfo = {
.parent = parent,
.name = name,
.id = -1,
+ .res = res,
+ .num_res = ARRAY_SIZE(res),
};
platform_device_register_full(&pdevinfo);
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 560e0df728f8..359f782c747d 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -589,7 +589,7 @@ void __init v2m_dt_init_early(void)
return;
/* Confirm board type against DT property, if available */
- if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
+ if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
int site = v2m_get_master_site();
u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index ce8cb1970d7a..89f2b7f7b042 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -279,7 +279,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
* You really shouldn't be using read() or write() on /dev/mem. This
* might go away in the future.
*/
-int valid_phys_addr_range(unsigned long addr, size_t size)
+int valid_phys_addr_range(phys_addr_t addr, size_t size)
{
if (addr < PHYS_OFFSET)
return 0;
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 86b8b480634f..09c5233f4dfc 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -89,7 +89,7 @@ ENTRY(cpu_v6_dcache_clean_area)
mov pc, lr
/*
- * cpu_arm926_switch_mm(pgd_phys, tsk)
+ * cpu_v6_switch_mm(pgd_phys, tsk)
*
* Set the translation table base pointer to be pgd_phys
*
diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
deleted file mode 100644
index c08a54d9d889..000000000000
--- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __PLAT_NOMADIK_GPIO
-#define __PLAT_NOMADIK_GPIO
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT 0x00
-#define NMK_GPIO_DATS 0x04
-#define NMK_GPIO_DATC 0x08
-#define NMK_GPIO_PDIS 0x0c
-#define NMK_GPIO_DIR 0x10
-#define NMK_GPIO_DIRS 0x14
-#define NMK_GPIO_DIRC 0x18
-#define NMK_GPIO_SLPC 0x1c
-#define NMK_GPIO_AFSLA 0x20
-#define NMK_GPIO_AFSLB 0x24
-#define NMK_GPIO_LOWEMI 0x28
-
-#define NMK_GPIO_RIMSC 0x40
-#define NMK_GPIO_FIMSC 0x44
-#define NMK_GPIO_IS 0x48
-#define NMK_GPIO_IC 0x4c
-#define NMK_GPIO_RWIMSC 0x50
-#define NMK_GPIO_FWIMSC 0x54
-#define NMK_GPIO_WKS 0x58
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO 0
-#define NMK_GPIO_ALT_A 1
-#define NMK_GPIO_ALT_B 2
-#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1 ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2 ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3 ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4 ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
- NMK_GPIO_PULL_NONE,
- NMK_GPIO_PULL_UP,
- NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
- NMK_GPIO_SLPM_INPUT,
- NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
- NMK_GPIO_SLPM_NOCHANGE,
- NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-extern int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode);
-extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
-#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);
-extern void nmk_gpio_wakeups_resume(void);
-
-extern void nmk_gpio_clocks_enable(void);
-extern void nmk_gpio_clocks_disable(void);
-
-extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
- char *name;
- int first_gpio;
- int first_irq;
- int num_gpio;
- u32 (*get_secondary_status)(unsigned int bank);
- void (*set_ioforce)(bool enable);
- bool supports_sleepmode;
-};
-
-#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index a5683a84c6ee..6013831a043e 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -26,12 +26,14 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
+#include <linux/i2c-omap.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <mach/irqs.h>
#include <plat/i2c.h>
+#include <plat/omap-pm.h>
#include <plat/omap_device.h>
#define OMAP_I2C_SIZE 0x3f
@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
#ifdef CONFIG_ARCH_OMAP2PLUS
+/*
+ * XXX This function is a temporary compatibility wrapper - only
+ * needed until the I2C driver can be converted to call
+ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
+ */
+static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
+{
+ omap_pm_set_max_mpu_wakeup_lat(dev, t);
+}
+
static inline int omap2_i2c_add_bus(int bus_id)
{
int l;
@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
pdata->flags = dev_attr->flags;
+ /*
+ * When waiting for completion of a i2c transfer, we need to
+ * set a wake up latency constraint for the MPU. This is to
+ * ensure quick enough wakeup from idle, when transfer
+ * completes.
+ * Only omap3 has support for constraints
+ */
+ if (cpu_is_omap34xx())
+ pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
pdev = omap_device_build(name, bus_id, oh, pdata,
sizeof(struct omap_i2c_bus_platform_data),
NULL, 0, 0);
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index 8b4e4f2da2f5..346af5b490be 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -126,6 +126,7 @@ struct omap_mmc_platform_data {
/* we can put the features above into this variable */
#define HSMMC_HAS_PBIAS (1 << 0)
#define HSMMC_HAS_UPDATED_RESET (1 << 1)
+#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
unsigned features;
int switch_pin; /* gpio (card detect) */
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index db98e7021f0d..0abd1c469887 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -473,12 +473,13 @@ int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
chan->number, __func__, buf);
- if (chan->end == NULL)
+ if (chan->end == NULL) {
pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
chan->number, __func__, chan);
-
- chan->end->next = buf;
- chan->end = buf;
+ } else {
+ chan->end->next = buf;
+ chan->end = buf;
+ }
}
/* if necessary, update the next buffer field */
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig
index f8db7b2deb36..87dbd81bdf51 100644
--- a/arch/arm/plat-spear/Kconfig
+++ b/arch/arm/plat-spear/Kconfig
@@ -12,6 +12,7 @@ config ARCH_SPEAR13XX
bool "ST SPEAr13xx with Device Tree"
select ARM_GIC
select CPU_V7
+ select GPIO_SPEAR_SPICS
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
select PINCTRL
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 364191f3be43..c95c5cb212fd 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -41,20 +41,24 @@ libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
# Default target when executing plain make
-KBUILD_IMAGE := Image.gz
+KBUILD_IMAGE := Image.gz
+KBUILD_DTBS := dtbs
-all: $(KBUILD_IMAGE)
+all: $(KBUILD_IMAGE) $(KBUILD_DTBS)
boot := arch/arm64/boot
Image Image.gz: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
zinstall install: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+ $(Q)$(MAKE) $(build)=$(boot) $@
-%.dtb:
- $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+%.dtb: scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+
+dtbs: scripts
+ $(Q)$(MAKE) $(build)=$(boot)/dts dtbs
# We use MRPROPER_FILES and CLEAN_FILES now
archclean:
@@ -63,6 +67,7 @@ archclean:
define archhelp
echo '* Image.gz - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+ echo '* dtbs - Build device tree blobs for enabled boards'
echo ' install - Install uncompressed kernel'
echo ' zinstall - Install compressed kernel'
echo ' Install using (your) ~/bin/installkernel or'
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index eca209b2b0bf..5a0e3ab854a5 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -22,9 +22,6 @@ $(obj)/Image: vmlinux FORCE
$(obj)/Image.gz: $(obj)/Image FORCE
$(call if_changed,gzip)
-$(obj)/%.dtb: $(src)/dts/%.dts
- $(call cmd,dtc)
-
install: $(obj)/Image
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
$(obj)/Image System.map "$(INSTALL_PATH)"
@@ -32,5 +29,3 @@ install: $(obj)/Image
zinstall: $(obj)/Image.gz
$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
$(obj)/Image.gz System.map "$(INSTALL_PATH)"
-
-clean-files += *.dtb
diff --git a/arch/arm64/boot/dts/.gitignore b/arch/arm64/boot/dts/.gitignore
new file mode 100644
index 000000000000..b60ed208c779
--- /dev/null
+++ b/arch/arm64/boot/dts/.gitignore
@@ -0,0 +1 @@
+*.dtb
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
new file mode 100644
index 000000000000..801e2d7fcbc6
--- /dev/null
+++ b/arch/arm64/boot/dts/Makefile
@@ -0,0 +1,5 @@
+targets += dtbs
+
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+
+clean-files := *.dtb
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 6d909faebf28..656a6f291a35 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -392,7 +392,7 @@ __SYSCALL(367, sys_fanotify_init)
__SYSCALL(368, compat_sys_fanotify_mark_wrapper)
__SYSCALL(369, sys_prlimit64)
__SYSCALL(370, sys_name_to_handle_at)
-__SYSCALL(371, sys_open_by_handle_at)
+__SYSCALL(371, compat_sys_open_by_handle_at)
__SYSCALL(372, sys_clock_adjtime)
__SYSCALL(373, sys_syncfs)
diff --git a/arch/c6x/Makefile b/arch/c6x/Makefile
index a9eb9597e03c..e72eb3417239 100644
--- a/arch/c6x/Makefile
+++ b/arch/c6x/Makefile
@@ -41,7 +41,7 @@ DTB:=$(subst dtbImage.,,$(filter dtbImage.%, $(MAKECMDGOALS)))
export DTB
ifneq ($(DTB),)
-core-y += $(boot)/
+core-y += $(boot)/dts/
endif
# With make 3.82 we cannot mix normal and wildcard targets
diff --git a/arch/c6x/boot/Makefile b/arch/c6x/boot/Makefile
index 6891257d514c..8734abee548e 100644
--- a/arch/c6x/boot/Makefile
+++ b/arch/c6x/boot/Makefile
@@ -6,25 +6,5 @@ OBJCOPYFLAGS_vmlinux.bin := -O binary
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
-DTC_FLAGS ?= -p 1024
-
-ifneq ($(DTB),)
-obj-y += linked_dtb.o
-endif
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
- $(call if_changed_dep,dtc)
-
-quiet_cmd_cp = CP $< $@$2
- cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
-
-# Generate builtin.dtb from $(DTB).dtb
-$(obj)/builtin.dtb: $(obj)/$(DTB).dtb
- $(call if_changed,cp)
-
-$(obj)/linked_dtb.o: $(obj)/builtin.dtb
-
$(obj)/dtbImage.%: vmlinux
$(call if_changed,objcopy)
-
-clean-files := $(obj)/*.dtb
diff --git a/arch/c6x/boot/dts/Makefile b/arch/c6x/boot/dts/Makefile
new file mode 100644
index 000000000000..c7528b02d061
--- /dev/null
+++ b/arch/c6x/boot/dts/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for device trees
+#
+
+DTC_FLAGS ?= -p 1024
+
+ifneq ($(DTB),)
+obj-y += linked_dtb.o
+endif
+
+quiet_cmd_cp = CP $< $@$2
+ cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
+
+# Generate builtin.dtb from $(DTB).dtb
+$(obj)/builtin.dtb: $(obj)/$(DTB).dtb
+ $(call if_changed,cp)
+
+$(obj)/linked_dtb.o: $(obj)/builtin.dtb
+
+clean-files := *.dtb
diff --git a/arch/c6x/boot/dts/linked_dtb.S b/arch/c6x/boot/dts/linked_dtb.S
new file mode 100644
index 000000000000..cf347f1d16ce
--- /dev/null
+++ b/arch/c6x/boot/dts/linked_dtb.S
@@ -0,0 +1,2 @@
+.section __fdt_blob,"a"
+.incbin "arch/c6x/boot/dts/builtin.dtb"
diff --git a/arch/c6x/boot/linked_dtb.S b/arch/c6x/boot/linked_dtb.S
deleted file mode 100644
index 57a4454eaec3..000000000000
--- a/arch/c6x/boot/linked_dtb.S
+++ /dev/null
@@ -1,2 +0,0 @@
-.section __fdt_blob,"a"
-.incbin "arch/c6x/boot/builtin.dtb"
diff --git a/arch/c6x/include/asm/setup.h b/arch/c6x/include/asm/setup.h
new file mode 100644
index 000000000000..ecead15872a6
--- /dev/null
+++ b/arch/c6x/include/asm/setup.h
@@ -0,0 +1,33 @@
+/*
+ * Port on Texas Instruments TMS320C6x architecture
+ *
+ * Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
+ * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_SETUP_H
+#define _ASM_C6X_SETUP_H
+
+#include <uapi/asm/setup.h>
+
+#ifndef __ASSEMBLY__
+extern char c6x_command_line[COMMAND_LINE_SIZE];
+
+extern int c6x_add_memory(phys_addr_t start, unsigned long size);
+
+extern unsigned long ram_start;
+extern unsigned long ram_end;
+
+extern int c6x_num_cores;
+extern unsigned int c6x_silicon_rev;
+extern unsigned int c6x_devstat;
+extern unsigned char c6x_fuse_mac[6];
+
+extern void machine_init(unsigned long dt_ptr);
+extern void time_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_C6X_SETUP_H */
diff --git a/arch/c6x/include/uapi/asm/Kbuild b/arch/c6x/include/uapi/asm/Kbuild
index c312b424c433..e9bc2b2b8147 100644
--- a/arch/c6x/include/uapi/asm/Kbuild
+++ b/arch/c6x/include/uapi/asm/Kbuild
@@ -1,6 +1,8 @@
# UAPI Header export list
include include/uapi/asm-generic/Kbuild.asm
+generic-y += kvm_para.h
+
header-y += byteorder.h
header-y += kvm_para.h
header-y += ptrace.h
diff --git a/arch/c6x/include/uapi/asm/kvm_para.h b/arch/c6x/include/uapi/asm/kvm_para.h
deleted file mode 100644
index 14fab8f0b957..000000000000
--- a/arch/c6x/include/uapi/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/c6x/include/uapi/asm/setup.h b/arch/c6x/include/uapi/asm/setup.h
index a01e31896fa9..ad9ac97a8dad 100644
--- a/arch/c6x/include/uapi/asm/setup.h
+++ b/arch/c6x/include/uapi/asm/setup.h
@@ -1,33 +1,6 @@
-/*
- * Port on Texas Instruments TMS320C6x architecture
- *
- * Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
- * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef _ASM_C6X_SETUP_H
-#define _ASM_C6X_SETUP_H
+#ifndef _UAPI_ASM_C6X_SETUP_H
+#define _UAPI_ASM_C6X_SETUP_H
#define COMMAND_LINE_SIZE 1024
-#ifndef __ASSEMBLY__
-extern char c6x_command_line[COMMAND_LINE_SIZE];
-
-extern int c6x_add_memory(phys_addr_t start, unsigned long size);
-
-extern unsigned long ram_start;
-extern unsigned long ram_end;
-
-extern int c6x_num_cores;
-extern unsigned int c6x_silicon_rev;
-extern unsigned int c6x_devstat;
-extern unsigned char c6x_fuse_mac[6];
-
-extern void machine_init(unsigned long dt_ptr);
-extern void time_init(void);
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_C6X_SETUP_H */
+#endif /* _UAPI_ASM_C6X_SETUP_H */
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S
index 5449c36018fe..0ed6157dd256 100644
--- a/arch/c6x/kernel/entry.S
+++ b/arch/c6x/kernel/entry.S
@@ -277,6 +277,8 @@ work_rescheduled:
[A1] BNOP .S1 work_resched,5
work_notifysig:
+ ;; enable interrupts for do_notify_resume()
+ UNMASK_INT B2
B .S2 do_notify_resume
LDW .D2T1 *+SP(REGS__END+8),A6 ; syscall flag
ADDKPC .S2 resume_userspace,B3,1
@@ -427,8 +429,7 @@ ENTRY(ret_from_kernel_execve)
ENDPROC(ret_from_kernel_execve)
;;
- ;; These are the interrupt handlers, responsible for calling __do_IRQ()
- ;; int6 is used for syscalls (see _system_call entry)
+ ;; These are the interrupt handlers, responsible for calling c6x_do_IRQ()
;;
.macro SAVE_ALL_INT
SAVE_ALL IRP,ITSR
diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h
index d05e78f6db94..f69c32ffbe6a 100644
--- a/arch/ia64/include/asm/device.h
+++ b/arch/ia64/include/asm/device.h
@@ -7,9 +7,6 @@
#define _ASM_IA64_DEVICE_H
struct dev_archdata {
-#ifdef CONFIG_ACPI
- void *acpi_handle;
-#endif
#ifdef CONFIG_INTEL_IOMMU
void *iommu; /* hook for IOMMU specific extension */
#endif
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 2c26321c28c3..74a7cc3293bc 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -90,7 +90,7 @@ phys_to_virt (unsigned long address)
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
+extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
/*
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 440578850ae5..e9682f5be343 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -633,6 +633,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
IOSAPIC_LEVEL);
}
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
void acpi_unregister_gsi(u32 gsi)
{
@@ -644,6 +645,7 @@ void acpi_unregister_gsi(u32 gsi)
iosapic_unregister_intr(gsi);
}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
static int __init acpi_parse_fadt(struct acpi_table_header *table)
{
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index d37bbd48637f..f034563aeae5 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -870,7 +870,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
EXPORT_SYMBOL(kern_mem_attribute);
int
-valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
+valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
{
u64 attr;
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
index 67e489d8d1bd..2df26b57c26a 100644
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -41,7 +41,7 @@ struct k_sigaction {
static inline void sigaddset(sigset_t *set, int _sig)
{
asm ("bfset %0{%1,#1}"
- : "+od" (*set)
+ : "+o" (*set)
: "id" ((_sig - 1) ^ 31)
: "cc");
}
@@ -49,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
static inline void sigdelset(sigset_t *set, int _sig)
{
asm ("bfclr %0{%1,#1}"
- : "+od" (*set)
+ : "+o" (*set)
: "id" ((_sig - 1) ^ 31)
: "cc");
}
@@ -65,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
int ret;
asm ("bfextu %1{%2,#1},%0"
: "=d" (ret)
- : "od" (*set), "id" ((_sig-1) ^ 31)
+ : "o" (*set), "id" ((_sig-1) ^ 31)
: "cc");
return ret;
}
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
index b23c40eb7a52..d26fb905ee0a 100644
--- a/arch/microblaze/Makefile
+++ b/arch/microblaze/Makefile
@@ -57,7 +57,7 @@ boot := arch/microblaze/boot
DTB:=$(subst simpleImage.,,$(filter simpleImage.%, $(MAKECMDGOALS)))
ifneq ($(DTB),)
- core-y += $(boot)/
+ core-y += $(boot)/dts/
endif
# defines filename extension depending memory management type
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile
index fa83ea497db7..80fe54fb7ca3 100644
--- a/arch/microblaze/boot/Makefile
+++ b/arch/microblaze/boot/Makefile
@@ -2,21 +2,10 @@
# arch/microblaze/boot/Makefile
#
-obj-y += linked_dtb.o
-
targets := linux.bin linux.bin.gz simpleImage.%
OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary
-# Ensure system.dtb exists
-$(obj)/linked_dtb.o: $(obj)/system.dtb
-
-# Generate system.dtb from $(DTB).dtb
-ifneq ($(DTB),system)
-$(obj)/system.dtb: $(obj)/$(DTB).dtb
- $(call if_changed,cp)
-endif
-
$(obj)/linux.bin: vmlinux FORCE
$(call if_changed,objcopy)
$(call if_changed,uimage)
@@ -45,10 +34,4 @@ $(obj)/simpleImage.%: vmlinux FORCE
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
-# Rule to build device tree blobs
-DTC_FLAGS := -p 1024
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
- $(call if_changed_dep,dtc)
-
-clean-files += *.dtb simpleImage.*.unstrip linux.bin.ub
+clean-files += simpleImage.*.unstrip linux.bin.ub
diff --git a/arch/microblaze/boot/dts/Makefile b/arch/microblaze/boot/dts/Makefile
new file mode 100644
index 000000000000..c3b3a5d67b89
--- /dev/null
+++ b/arch/microblaze/boot/dts/Makefile
@@ -0,0 +1,22 @@
+#
+# arch/microblaze/boot/Makefile
+#
+
+obj-y += linked_dtb.o
+
+# Ensure system.dtb exists
+$(obj)/linked_dtb.o: $(obj)/system.dtb
+
+# Generate system.dtb from $(DTB).dtb
+ifneq ($(DTB),system)
+$(obj)/system.dtb: $(obj)/$(DTB).dtb
+ $(call if_changed,cp)
+endif
+
+quiet_cmd_cp = CP $< $@$2
+ cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
+
+# Rule to build device tree blobs
+DTC_FLAGS := -p 1024
+
+clean-files += *.dtb
diff --git a/arch/microblaze/boot/dts/linked_dtb.S b/arch/microblaze/boot/dts/linked_dtb.S
new file mode 100644
index 000000000000..23345af3721f
--- /dev/null
+++ b/arch/microblaze/boot/dts/linked_dtb.S
@@ -0,0 +1,2 @@
+.section __fdt_blob,"a"
+.incbin "arch/microblaze/boot/dts/system.dtb"
diff --git a/arch/microblaze/boot/linked_dtb.S b/arch/microblaze/boot/linked_dtb.S
deleted file mode 100644
index cb2b537aebee..000000000000
--- a/arch/microblaze/boot/linked_dtb.S
+++ /dev/null
@@ -1,3 +0,0 @@
-.section __fdt_blob,"a"
-.incbin "arch/microblaze/boot/system.dtb"
-
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 3847e5b9c601..3903e3d11f5a 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -111,7 +111,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1) == -EFAULT)
goto badframe;
return rval;
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 4dbb5055d04b..a1c5b996d66d 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1346,8 +1346,6 @@ void __init pcibios_resource_survey(void)
pci_assign_unassigned_resources();
}
-#ifdef CONFIG_HOTPLUG
-
/* This is used by the PCI hotplug driver to allocate resource
* of newly plugged busses. We can try to consolidate with the
* rest of the code later, for now, keep it as-is as our main
@@ -1407,8 +1405,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
-#endif /* CONFIG_HOTPLUG */
-
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
return pci_enable_resources(dev, mask);
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index bc96e2908f14..6e927cf20df2 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -24,9 +24,6 @@ DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
-$(obj)/%.dtb: $(src)/%.dts FORCE
- $(call if_changed_dep,dtc)
-
# Let's keep the .dtb files around in case we want to look at them.
.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h
index bd94946a18f3..ef99db994c2f 100644
--- a/arch/mips/include/asm/hugetlb.h
+++ b/arch/mips/include/asm/hugetlb.h
@@ -95,7 +95,17 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
pte_t *ptep, pte_t pte,
int dirty)
{
- return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+ int changed = !pte_same(*ptep, pte);
+
+ if (changed) {
+ set_pte_at(vma->vm_mm, addr, ptep, pte);
+ /*
+ * There could be some standard sized pages in there,
+ * get them all.
+ */
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+ }
+ return changed;
}
static inline pte_t huge_ptep_get(pte_t *ptep)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index b1fb7af3c350..cce3782c96c9 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -510,7 +510,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
c->cputype = CPU_R3000A;
__cpu_name[cpu] = "R3000A";
}
- break;
} else {
c->cputype = CPU_R3000;
__cpu_name[cpu] = "R3000";
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index a6c133212003..9b00362f32f6 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -36,6 +36,11 @@ FEXPORT(ret_from_exception)
FEXPORT(ret_from_irq)
LONG_S s0, TI_REGS($28)
FEXPORT(__ret_from_irq)
+/*
+ * We can be coming here from a syscall done in the kernel space,
+ * e.g. a failed kernel_execve().
+ */
+resume_userspace_check:
LONG_L t0, PT_STATUS(sp) # returning to kernel mode?
andi t0, t0, KU_USER
beqz t0, resume_kernel
@@ -162,7 +167,7 @@ work_notifysig: # deal with pending signals and
move a0, sp
li a1, 0
jal do_notify_resume # a2 already loaded
- j resume_userspace
+ j resume_userspace_check
FEXPORT(syscall_exit_partial)
local_irq_disable # make sure need_resched doesn't
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index f6ba8381ee01..86ec03f0e00c 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -397,14 +397,14 @@ EXPORT(sysn32_call_table)
PTR sys_timerfd_create
PTR compat_sys_timerfd_gettime /* 6285 */
PTR compat_sys_timerfd_settime
- PTR sys_signalfd4
+ PTR compat_sys_signalfd4
PTR sys_eventfd2
PTR sys_epoll_create1
PTR sys_dup3 /* 6290 */
PTR sys_pipe2
PTR sys_inotify_init1
- PTR sys_preadv
- PTR sys_pwritev
+ PTR compat_sys_preadv
+ PTR compat_sys_pwritev
PTR compat_sys_rt_tgsigqueueinfo /* 6295 */
PTR sys_perf_event_open
PTR sys_accept4
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index a53f8ec37aac..290dc6a1d7a3 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
void __init add_memory_region(phys_t start, phys_t size, long type)
{
int x = boot_mem_map.nr_map;
- struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+ int i;
/* Sanity check */
if (start + size < start) {
@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
}
/*
- * Try to merge with previous entry if any. This is far less than
- * perfect but is sufficient for most real world cases.
+ * Try to merge with existing entry, if any.
*/
- if (x && prev->addr + prev->size == start && prev->type == type) {
- prev->size += size;
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+ unsigned long top;
+
+ if (entry->type != type)
+ continue;
+
+ if (start + size < entry->addr)
+ continue; /* no overlap */
+
+ if (entry->addr + entry->size < start)
+ continue; /* no overlap */
+
+ top = max(entry->addr + entry->size, start + size);
+ entry->addr = min(entry->addr, start);
+ entry->size = top - entry->addr;
+
return;
}
- if (x == BOOT_MEM_MAP_MAX) {
+ if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
pr_err("Ooops! Too many entries in the memory map!\n");
return;
}
diff --git a/arch/mips/lantiq/dts/Makefile b/arch/mips/lantiq/dts/Makefile
index 674fca45f72d..6fa72dd641b2 100644
--- a/arch/mips/lantiq/dts/Makefile
+++ b/arch/mips/lantiq/dts/Makefile
@@ -1,4 +1 @@
obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
-
-$(obj)/%.dtb: $(obj)/%.dts
- $(call if_changed,dtc)
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
index e091430dbeb1..cd160be3ce4d 100644
--- a/arch/mips/lib/mips-atomic.c
+++ b/arch/mips/lib/mips-atomic.c
@@ -56,7 +56,7 @@ __asm__(
" .set pop \n"
" .endm \n");
-void arch_local_irq_disable(void)
+notrace void arch_local_irq_disable(void)
{
preempt_disable();
__asm__ __volatile__(
@@ -93,7 +93,7 @@ __asm__(
" .set pop \n"
" .endm \n");
-unsigned long arch_local_irq_save(void)
+notrace unsigned long arch_local_irq_save(void)
{
unsigned long flags;
preempt_disable();
@@ -135,7 +135,7 @@ __asm__(
" .set pop \n"
" .endm \n");
-void arch_local_irq_restore(unsigned long flags)
+notrace void arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
@@ -159,7 +159,7 @@ void arch_local_irq_restore(unsigned long flags)
EXPORT_SYMBOL(arch_local_irq_restore);
-void __arch_local_irq_restore(unsigned long flags)
+notrace void __arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 4b9b935a070e..88e79ad6f811 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -120,18 +120,11 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
if (cpu_context(cpu, mm) != 0) {
unsigned long size, flags;
- int huge = is_vm_hugetlb_page(vma);
ENTER_CRITICAL(flags);
- if (huge) {
- start = round_down(start, HPAGE_SIZE);
- end = round_up(end, HPAGE_SIZE);
- size = (end - start) >> HPAGE_SHIFT;
- } else {
- start = round_down(start, PAGE_SIZE << 1);
- end = round_up(end, PAGE_SIZE << 1);
- size = (end - start) >> (PAGE_SHIFT + 1);
- }
+ start = round_down(start, PAGE_SIZE << 1);
+ end = round_up(end, PAGE_SIZE << 1);
+ size = (end - start) >> (PAGE_SHIFT + 1);
if (size <= current_cpu_data.tlbsize/2) {
int oldpid = read_c0_entryhi();
int newpid = cpu_asid(cpu, mm);
@@ -140,10 +133,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
int idx;
write_c0_entryhi(start | newpid);
- if (huge)
- start += HPAGE_SIZE;
- else
- start += (PAGE_SIZE << 1);
+ start += (PAGE_SIZE << 1);
mtc0_tlbw_hazard();
tlb_probe();
tlb_probe_hazard();
diff --git a/arch/mips/netlogic/dts/Makefile b/arch/mips/netlogic/dts/Makefile
index 67ae3fe296f0..d117d46413aa 100644
--- a/arch/mips/netlogic/dts/Makefile
+++ b/arch/mips/netlogic/dts/Makefile
@@ -1,4 +1 @@
obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o
-
-$(obj)/%.dtb: $(obj)/%.dts
- $(call if_changed,dtc)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 04e35bcde07c..4040416e0603 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -313,10 +313,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
}
}
-#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
-#endif
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
index 966886c8daf5..4739b8302a58 100644
--- a/arch/openrisc/Makefile
+++ b/arch/openrisc/Makefile
@@ -50,6 +50,6 @@ BUILTIN_DTB := y
else
BUILTIN_DTB := n
endif
-core-$(BUILTIN_DTB) += arch/openrisc/boot/
+core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
all: vmlinux
diff --git a/arch/openrisc/boot/Makefile b/arch/openrisc/boot/dts/Makefile
index 09958358601a..b092d30d6c23 100644
--- a/arch/openrisc/boot/Makefile
+++ b/arch/openrisc/boot/dts/Makefile
@@ -1,5 +1,3 @@
-
-
ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
else
@@ -10,6 +8,3 @@ obj-y += $(BUILTIN_DTB)
clean-files := *.dtb.S
#DTC_FLAGS ?= -p 1024
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
- $(call if_changed_dep,dtc)
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 30110297f4f9..ddedc8a77861 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -84,7 +84,6 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
sigset_t set;
- stack_t st;
/*
* Since we stacked the signal on a dword boundary,
@@ -104,11 +103,10 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
- goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->sp);
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+ goto badframe;
return regs->gpr[11];
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index fd49aeda9eb8..5dede04f2f3e 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
{
compat_sigset_t s;
- if (sz != sizeof *set) panic("put_sigset32()");
+ if (sz != sizeof *set)
+ return -EINVAL;
sigset_64to32(&s, set);
return copy_to_user(up, &s, sizeof s);
@@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
compat_sigset_t s;
int r;
- if (sz != sizeof *set) panic("put_sigset32()");
+ if (sz != sizeof *set)
+ return -EINVAL;
if ((r = copy_from_user(&s, up, sz)) == 0) {
sigset_32to64(set, &s);
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 7426e40699bd..f76c10863c62 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping,
struct vm_area_struct *vma;
int offset = mapping ? get_offset(mapping) : 0;
+ offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000;
+
addr = DCACHE_ALIGN(addr - offset) + offset;
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 3735abd7f8f6..cbf5d59d5d6a 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -60,7 +60,7 @@
ENTRY_SAME(fork_wrapper)
ENTRY_SAME(read)
ENTRY_SAME(write)
- ENTRY_SAME(open) /* 5 */
+ ENTRY_COMP(open) /* 5 */
ENTRY_SAME(close)
ENTRY_SAME(waitpid)
ENTRY_SAME(creat)
diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi
index 7ab286ab5300..39ed65a44c5f 100644
--- a/arch/powerpc/boot/dts/mpc5200b.dtsi
+++ b/arch/powerpc/boot/dts/mpc5200b.dtsi
@@ -231,6 +231,12 @@
interrupts = <2 7 0>;
};
+ sclpc@3c00 {
+ compatible = "fsl,mpc5200-lpbfifo";
+ reg = <0x3c00 0x60>;
+ interrupts = <2 23 0>;
+ };
+
i2c@3d00 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi
index 3444eb8f0ade..24f668039295 100644
--- a/arch/powerpc/boot/dts/o2d.dtsi
+++ b/arch/powerpc/boot/dts/o2d.dtsi
@@ -86,12 +86,6 @@
reg = <0>;
};
};
-
- sclpc@3c00 {
- compatible = "fsl,mpc5200-lpbfifo";
- reg = <0x3c00 0x60>;
- interrupts = <3 23 0>;
- };
};
localbus {
diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts
index 9e354997eb7e..96512c058033 100644
--- a/arch/powerpc/boot/dts/pcm030.dts
+++ b/arch/powerpc/boot/dts/pcm030.dts
@@ -59,7 +59,7 @@
#gpio-cells = <2>;
};
- psc@2000 { /* PSC1 in ac97 mode */
+ audioplatform: psc@2000 { /* PSC1 in ac97 mode */
compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
cell-index = <0>;
};
@@ -134,4 +134,9 @@
localbus {
status = "disabled";
};
+
+ sound {
+ compatible = "phytec,pcm030-audio-fabric";
+ asoc-platform = <&audioplatform>;
+ };
};
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7f94f760dd0c..abc0d0856994 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1428,8 +1428,6 @@ void __init pcibios_resource_survey(void)
ppc_md.pcibios_fixup();
}
-#ifdef CONFIG_HOTPLUG
-
/* This is used by the PCI hotplug driver to allocate resource
* of newly plugged busses. We can try to consolidate with the
* rest of the code later, for now, keep it as-is as our main
@@ -1488,8 +1486,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
-#endif /* CONFIG_HOTPLUG */
-
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
if (ppc_md.pcibios_enable_device_hook)
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4ff190ff24a0..2cbe6768fddd 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -74,8 +74,6 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init);
-#ifdef CONFIG_HOTPLUG
-
int pcibios_unmap_io_space(struct pci_bus *bus)
{
struct pci_controller *hose;
@@ -124,8 +122,6 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
-#endif /* CONFIG_HOTPLUG */
-
static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
{
struct vm_struct *area;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 8520b58a5e9a..b89ef65392dc 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,
case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
- default:
- pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
- __func__, virq, l1irq, l2irq);
- return -EINVAL;
+ case MPC52xx_IRQ_L1_CRIT:
+ pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
+ __func__, l2irq);
+ irq_set_chip(virq, &no_irq_chip);
+ return 0;
}
irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index b0c3777528a1..d588e48dff74 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -686,7 +686,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
int count = 0;
for (pp = dev->node->properties; pp != 0; pp = pp->next) {
- char *name;
+ const char *name;
if (strncmp(pp->name, PP_PREFIX, plen) != 0)
continue;
name = pp->name + plen;
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c
index 797cd181dc3f..d16c8ded1084 100644
--- a/arch/powerpc/platforms/pseries/eeh_pe.c
+++ b/arch/powerpc/platforms/pseries/eeh_pe.c
@@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
if (list_empty(&pe->edevs)) {
cnt = 0;
list_for_each_entry(child, &pe->child_list, child) {
- if (!(pe->type & EEH_PE_INVALID)) {
+ if (!(child->type & EEH_PE_INVALID)) {
cnt++;
break;
}
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index d19f4977c834..e5b084723131 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
/* Get the top level device in the PE */
edev = of_node_to_eeh_dev(dn);
- edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+ if (edev->pe)
+ edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
dn = eeh_dev_to_of_node(edev);
if (!dn)
return NULL;
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
index 45d00e5fe14d..4d806b419606 100644
--- a/arch/powerpc/platforms/pseries/processor_idle.c
+++ b/arch/powerpc/platforms/pseries/processor_idle.c
@@ -36,7 +36,7 @@ static struct cpuidle_state *cpuidle_state_table;
static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
{
- *kt_before = ktime_get_real();
+ *kt_before = ktime_get();
*in_purr = mfspr(SPRN_PURR);
/*
* Indicate to the HV that we are idle. Now would be
@@ -50,7 +50,7 @@ static inline s64 idle_loop_epilog(unsigned long in_purr, ktime_t kt_before)
get_lppaca()->wait_state_cycles += mfspr(SPRN_PURR) - in_purr;
get_lppaca()->idle = 0;
- return ktime_to_us(ktime_sub(ktime_get_real(), kt_before));
+ return ktime_to_us(ktime_sub(ktime_get(), kt_before));
}
static int snooze_loop(struct cpuidle_device *dev,
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 39f71fba9b38..2f4668136b20 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -281,12 +281,11 @@ static struct property *new_property(const char *name, const int length,
if (!new)
return NULL;
- if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
+ if (!(new->name = kstrdup(name, GFP_KERNEL)))
goto cleanup;
if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
goto cleanup;
- strcpy(new->name, name);
memcpy(new->value, value, length);
*(((char *)new->value) + length) = 0;
new->length = length;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index ffb93ae9379b..01b62a62c635 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -136,7 +136,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
u32 pcicsrbar = 0, pcicsrbar_sz;
u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
- char *name = hose->dn->full_name;
+ const char *name = hose->dn->full_name;
const u64 *reg;
int len;
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 702256a1ca11..9193e12df695 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -157,7 +157,7 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
ent->map = SCOM_MAP_INVALID;
spin_lock_init(&ent->lock);
snprintf(ent->name, 8, "scom%d", i);
- ent->blob.data = dn->full_name;
+ ent->blob.data = (void*) dn->full_name;
ent->blob.size = strlen(dn->full_name);
dir = debugfs_create_dir(ent->name, root);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index ad79b846535c..827e094a2f49 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -28,7 +28,7 @@ ENTRY(sys32_open_wrapper)
llgtr %r2,%r2 # const char *
lgfr %r3,%r3 # int
lgfr %r4,%r4 # int
- jg sys_open # branch to system call
+ jg compat_sys_open # branch to system call
ENTRY(sys32_close_wrapper)
llgfr %r2,%r2 # unsigned int
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c
index c268bbf8b410..02353bde92d8 100644
--- a/arch/score/kernel/signal.c
+++ b/arch/score/kernel/signal.c
@@ -148,7 +148,6 @@ score_rt_sigreturn(struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
sigset_t set;
- stack_t st;
int sig;
/* Always make any pending restarted system calls return -EINTR */
@@ -168,12 +167,10 @@ score_rt_sigreturn(struct pt_regs *regs)
else if (sig)
force_sig(sig, current);
- if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
- goto badframe;
-
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
+ if (do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs->regs[0]) == -EFAULT)
+ goto badframe;
regs->is_syscall = 0;
__asm__ __volatile__(
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index a7e078f2e2e4..81e5dafed3e4 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -319,7 +319,5 @@ EXPORT_SYMBOL(pci_iounmap);
#endif /* CONFIG_GENERIC_IOMAP */
-#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(PCIBIOS_MIN_IO);
EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
-#endif
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 73a23f4617a3..629db2ad7916 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -382,7 +382,7 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
#define xlate_dev_kmem_ptr(p) p
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-int valid_phys_addr_range(unsigned long addr, size_t size);
+int valid_phys_addr_range(phys_addr_t addr, size_t size);
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
#endif /* __KERNEL__ */
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 23853814bd17..d867cd95a622 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -347,7 +347,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
{
struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
sigset_t set;
- stack_t __user st;
long long ret;
/* Always make any pending restarted system calls return -EINTR */
@@ -365,11 +364,10 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
goto badframe;
regs->pc -= 4;
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
- goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack(&st, NULL, REF_REG_SP);
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, REF_REG_SP) == -EFAULT)
+ goto badframe;
return (int) ret;
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
index afeb710ec5c3..80bf494ddbcb 100644
--- a/arch/sh/mm/mmap.c
+++ b/arch/sh/mm/mmap.c
@@ -238,7 +238,7 @@ bottomup:
* You really shouldn't be using read() or write() on /dev/mem. This
* might go away in the future.
*/
-int valid_phys_addr_range(unsigned long addr, size_t count)
+int valid_phys_addr_range(phys_addr_t addr, size_t count)
{
if (addr < __MEMORY_START)
return 0;
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
index c0a798fcf030..bb7c95161d71 100644
--- a/arch/sparc/boot/piggyback.c
+++ b/arch/sparc/boot/piggyback.c
@@ -81,18 +81,18 @@ static void usage(void)
static int start_line(const char *line)
{
- if (strcmp(line + 8, " T _start\n") == 0)
+ if (strcmp(line + 10, " _start\n") == 0)
return 1;
- else if (strcmp(line + 16, " T _start\n") == 0)
+ else if (strcmp(line + 18, " _start\n") == 0)
return 1;
return 0;
}
static int end_line(const char *line)
{
- if (strcmp(line + 8, " A _end\n") == 0)
+ if (strcmp(line + 10, " _end\n") == 0)
return 1;
- else if (strcmp (line + 16, " A _end\n") == 0)
+ else if (strcmp (line + 18, " _end\n") == 0)
return 1;
return 0;
}
@@ -100,8 +100,8 @@ static int end_line(const char *line)
/*
* Find address for start and end in System.map.
* The file looks like this:
- * f0004000 T _start
- * f0379f79 A _end
+ * f0004000 ... _start
+ * f0379f79 ... _end
* 1234567890123456
* ^coloumn 1
* There is support for 64 bit addresses too.
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index f93003123bce..67c62578d170 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -63,10 +63,13 @@ extern char *of_console_options;
extern void irq_trans_init(struct device_node *dp);
extern char *build_path_component(struct device_node *dp);
-/* SPARC has a local implementation */
+/* SPARC has local implementations */
extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r);
#define of_address_to_resource of_address_to_resource
+void __iomem *of_iomap(struct device_node *node, int index);
+#define of_iomap of_iomap
+
#endif /* __KERNEL__ */
#endif /* _SPARC_PROM_H */
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 918a2031c8bb..5f688531f48c 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -88,7 +88,7 @@ struct pci_pbm_info {
int chip_revision;
/* Name used for top-level resources. */
- char *name;
+ const char *name;
/* OBP specific information. */
struct platform_device *op;
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 867de2f8189c..689e1ba62809 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
err |= restore_fpu_state(regs, fpu_save);
err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
- err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
- if (err)
+ if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
goto segv;
err |= __get_user(rwin_save, &sf->rwin_save);
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index 44025f4ba41f..8475a474273a 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -47,7 +47,7 @@ STUB: sra REG1, 0, REG1; \
sra REG4, 0, REG4
SIGN1(sys32_exit, sparc_exit, %o0)
-SIGN1(sys32_exit_group, sys_exit_group, %o0)
+SIGN1(sys32_exit_group, sparc_exit_group, %o0)
SIGN1(sys32_wait4, compat_sys_wait4, %o2)
SIGN1(sys32_creat, sys_creat, %o1)
SIGN1(sys32_mknod, sys_mknod, %o1)
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 7f5f65d0b3fd..bf2347794e33 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -118,10 +118,20 @@ ret_from_syscall:
ba,pt %xcc, ret_sys_call
ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
+ .globl sparc_exit_group
+ .type sparc_exit_group,#function
+sparc_exit_group:
+ sethi %hi(sys_exit_group), %g7
+ ba,pt %xcc, 1f
+ or %g7, %lo(sys_exit_group), %g7
+ .size sparc_exit_group,.-sparc_exit_group
+
.globl sparc_exit
.type sparc_exit,#function
sparc_exit:
- rdpr %pstate, %g2
+ sethi %hi(sys_exit), %g7
+ or %g7, %lo(sys_exit), %g7
+1: rdpr %pstate, %g2
wrpr %g2, PSTATE_IE, %pstate
rdpr %otherwin, %g1
rdpr %cansave, %g3
@@ -129,7 +139,7 @@ sparc_exit:
wrpr %g3, 0x0, %cansave
wrpr %g0, 0x0, %otherwin
wrpr %g2, 0x0, %pstate
- ba,pt %xcc, sys_exit
+ jmpl %g7, %g0
stb %g0, [%g6 + TI_WSAVED]
.size sparc_exit,.-sparc_exit
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 1c9af9fa38e9..017b74a63dcb 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -133,7 +133,7 @@ sys_call_table:
/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
- .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
+ .word sys_setpgid, sys_fremovexattr, sys_tkill, sparc_exit_group, sys_newuname
/*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
.word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask
/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 3a8ece7d09ca..0d7103c9eff3 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -32,13 +32,14 @@ void flush_thread(void)
"err = %d\n", ret);
force_sig(SIGKILL, current);
}
+ get_safe_registers(current_pt_regs()->regs.gp,
+ current_pt_regs()->regs.fp);
__switch_mm(&current->mm->context.id);
}
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
- get_safe_registers(regs->regs.gp, regs->regs.fp);
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
current->ptrace &= ~PT_DTRACE;
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index b0056f68d321..7c4359240b81 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -250,9 +250,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
}
-#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pcibios_fixup_bus);
-#endif
static int __init pci_common_init(void)
{
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c760e073963e..e87b0cac14b5 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -12,6 +12,8 @@
#include <asm/setup.h>
#include <asm/desc.h>
+#undef memcpy /* Use memcpy from misc.c */
+
#include "eboot.h"
static efi_system_table_t *sys_table;
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 2a017441b8b2..8c132a625b94 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -476,6 +476,3 @@ die:
setup_corrupt:
.byte 7
.string "No setup signature found...\n"
-
- .data
-dummy: .long 0
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 66e5f0ef0523..79fd8a3418f9 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,6 +12,7 @@ header-y += mce.h
header-y += msr-index.h
header-y += msr.h
header-y += mtrr.h
+header-y += perf_regs.h
header-y += posix_types_32.h
header-y += posix_types_64.h
header-y += posix_types_x32.h
@@ -19,8 +20,10 @@ header-y += prctl.h
header-y += processor-flags.h
header-y += ptrace-abi.h
header-y += sigcontext32.h
+header-y += svm.h
header-y += ucontext.h
header-y += vm86.h
+header-y += vmx.h
header-y += vsyscall.h
genhdr-y += unistd_32.h
diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h
index 93e1c55f14ab..03dd72957d2f 100644
--- a/arch/x86/include/asm/device.h
+++ b/arch/x86/include/asm/device.h
@@ -2,9 +2,6 @@
#define _ASM_X86_DEVICE_H
struct dev_archdata {
-#ifdef CONFIG_ACPI
- void *acpi_handle;
-#endif
#ifdef CONFIG_X86_DEV_DMA_OPS
struct dma_map_ops *dma_ops;
#endif
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 831dbb9c6c02..41ab26ea6564 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -399,14 +399,17 @@ static inline void drop_init_fpu(struct task_struct *tsk)
typedef struct { int preload; } fpu_switch_t;
/*
- * FIXME! We could do a totally lazy restore, but we need to
- * add a per-cpu "this was the task that last touched the FPU
- * on this CPU" variable, and the task needs to have a "I last
- * touched the FPU on this CPU" and check them.
+ * Must be run with preemption disabled: this clears the fpu_owner_task,
+ * on this CPU.
*
- * We don't do that yet, so "fpu_lazy_restore()" always returns
- * false, but some day..
+ * This will disable any lazy FPU state restore of the current FPU state,
+ * but if the current thread owns the FPU, it will still be saved by.
*/
+static inline void __cpu_disable_lazy_restore(unsigned int cpu)
+{
+ per_cpu(fpu_owner_task, cpu) = NULL;
+}
+
static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
{
return new == this_cpu_read_stable(fpu_owner_task) &&
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index dcfde52979c3..19f16ebaf4fa 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
}
#endif
-/*
- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
- * when it traps. The previous stack will be directly underneath the saved
- * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
- *
- * This is valid only for kernel mode traps.
- */
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
-{
#ifdef CONFIG_X86_32
- return (unsigned long)(&regs->sp);
+extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
#else
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
return regs->sp;
-#endif
}
+#endif
#define GET_IP(regs) ((regs)->ip)
#define GET_FP(regs) ((regs)->bp)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e651f7a589ac..e48cafcf92ae 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -574,6 +574,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
return irq;
}
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
+
+void acpi_unregister_gsi(u32 gsi)
+{
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
void __init acpi_set_irq_model_pic(void)
{
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 11676cf65aee..d5e0d717005a 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -101,6 +101,8 @@ static int __init acpi_sleep_setup(char *str)
#endif
if (strncmp(str, "nonvs", 5) == 0)
acpi_nvs_nosave();
+ if (strncmp(str, "nonvs_s3", 8) == 0)
+ acpi_nvs_nosave_s3();
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ',');
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f7e98a2c0d12..1b7d1656a042 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
}
}
+ /*
+ * The way access filter has a performance penalty on some workloads.
+ * Disable it on the affected CPUs.
+ */
+ if ((c->x86 == 0x15) &&
+ (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+ u64 val;
+
+ if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+ val |= 0x1E;
+ wrmsrl_safe(0xc0011021, val);
+ }
+ }
+
cpu_detect_cache_sizes(c);
/* Multi core CPU? */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 698b6ec12e0f..1ac581f38dfa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -6,7 +6,7 @@
*
* Written by Jacob Shin - AMD, Inc.
*
- * Support: borislav.petkov@amd.com
+ * Maintained by: Borislav Petkov <bp@alien8.de>
*
* April 2006
* - added support for AMD Family 0x10 processors
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 5f88abf07e9c..4f9a3cbfc4a3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -285,34 +285,39 @@ void cmci_clear(void)
raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
}
+static long cmci_rediscover_work_func(void *arg)
+{
+ int banks;
+
+ /* Recheck banks in case CPUs don't all have the same */
+ if (cmci_supported(&banks))
+ cmci_discover(banks);
+
+ return 0;
+}
+
/*
* After a CPU went down cycle through all the others and rediscover
* Must run in process context.
*/
void cmci_rediscover(int dying)
{
- int banks;
- int cpu;
- cpumask_var_t old;
+ int cpu, banks;
if (!cmci_supported(&banks))
return;
- if (!alloc_cpumask_var(&old, GFP_KERNEL))
- return;
- cpumask_copy(old, &current->cpus_allowed);
for_each_online_cpu(cpu) {
if (cpu == dying)
continue;
- if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+
+ if (cpu == smp_processor_id()) {
+ cmci_rediscover_work_func(NULL);
continue;
- /* Recheck banks in case CPUs don't all have the same */
- if (cmci_supported(&banks))
- cmci_discover(banks);
- }
+ }
- set_cpus_allowed_ptr(current, old);
- free_cpumask_var(old);
+ work_on_cpu(cpu, cmci_rediscover_work_func, NULL);
+ }
}
/*
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b51b2c7ee51f..1328fe49a3f1 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -995,8 +995,8 @@ END(interrupt)
*/
.p2align CONFIG_X86_L1_CACHE_SHIFT
common_interrupt:
- ASM_CLAC
XCPT_FRAME
+ ASM_CLAC
addq $-0x80,(%rsp) /* Adjust vector to [-256,-1] range */
interrupt do_IRQ
/* 0(%rsp): old_rsp-ARGOFFSET */
@@ -1135,8 +1135,8 @@ END(common_interrupt)
*/
.macro apicinterrupt num sym do_sym
ENTRY(\sym)
- ASM_CLAC
INTR_FRAME
+ ASM_CLAC
pushq_cfi $~(\num)
.Lcommon_\sym:
interrupt \do_sym
@@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \
*/
.macro zeroentry sym do_sym
ENTRY(\sym)
- ASM_CLAC
INTR_FRAME
+ ASM_CLAC
PARAVIRT_ADJUST_EXCEPTION_FRAME
pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
subq $ORIG_RAX-R15, %rsp
@@ -1208,8 +1208,8 @@ END(\sym)
.macro paranoidzeroentry sym do_sym
ENTRY(\sym)
- ASM_CLAC
INTR_FRAME
+ ASM_CLAC
PARAVIRT_ADJUST_EXCEPTION_FRAME
pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
subq $ORIG_RAX-R15, %rsp
@@ -1227,8 +1227,8 @@ END(\sym)
#define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
.macro paranoidzeroentry_ist sym do_sym ist
ENTRY(\sym)
- ASM_CLAC
INTR_FRAME
+ ASM_CLAC
PARAVIRT_ADJUST_EXCEPTION_FRAME
pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
subq $ORIG_RAX-R15, %rsp
@@ -1247,8 +1247,8 @@ END(\sym)
.macro errorentry sym do_sym
ENTRY(\sym)
- ASM_CLAC
XCPT_FRAME
+ ASM_CLAC
PARAVIRT_ADJUST_EXCEPTION_FRAME
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1266,8 +1266,8 @@ END(\sym)
/* error code is on the stack already */
.macro paranoiderrorentry sym do_sym
ENTRY(\sym)
- ASM_CLAC
XCPT_FRAME
+ ASM_CLAC
PARAVIRT_ADJUST_EXCEPTION_FRAME
subq $ORIG_RAX-R15, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 957a47aec64e..4dac2f68ed4a 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -292,8 +292,8 @@ default_entry:
* be using the global pages.
*
* NOTE! If we are on a 486 we may have no cr4 at all!
- * Specifically, cr4 exists if and only if CPUID exists,
- * which in turn exists if and only if EFLAGS.ID exists.
+ * Specifically, cr4 exists if and only if CPUID exists
+ * and has flags other than the FPU flag set.
*/
movl $X86_EFLAGS_ID,%ecx
pushl %ecx
@@ -308,6 +308,11 @@ default_entry:
testl %ecx,%eax
jz 6f # No ID flag = no CPUID = no CR4
+ movl $1,%eax
+ cpuid
+ andl $~1,%edx # Ignore CPUID.FPU
+ jz 6f # No flags or only CPUID.FPU = no CR4
+
movl pa(mmu_cr4_features),%eax
movl %eax,%cr4
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 7720ff5a9ee2..efdec7cd8e01 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -8,8 +8,8 @@
* Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
*
* Maintainers:
- * Andreas Herrmann <andreas.herrmann3@amd.com>
- * Borislav Petkov <borislav.petkov@amd.com>
+ * Andreas Herrmann <herrmann.der.user@googlemail.com>
+ * Borislav Petkov <bp@alien8.de>
*
* This driver allows to upgrade microcode on F10h AMD
* CPUs and later.
@@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
#define F1XH_MPB_MAX_SIZE 2048
#define F14H_MPB_MAX_SIZE 1824
#define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
switch (c->x86) {
case 0x14:
@@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
case 0x15:
max_size = F15H_MPB_MAX_SIZE;
break;
+ case 0x16:
+ max_size = F16H_MPB_MAX_SIZE;
+ break;
default:
max_size = F1XH_MPB_MAX_SIZE;
break;
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index b00b33a18390..974b67e46dd0 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -22,6 +22,7 @@
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <linux/rcupdate.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value)
#define FLAG_MASK FLAG_MASK_32
+/*
+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
+ * when it traps. The previous stack will be directly underneath the saved
+ * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
+ *
+ * Now, if the stack is empty, '&regs->sp' is out of range. In this
+ * case we try to take the previous stack. To always return a non-null
+ * stack pointer we fall back to regs as stack if no previous stack
+ * exists.
+ *
+ * This is valid only for kernel mode traps.
+ */
+unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+ unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
+ unsigned long sp = (unsigned long)&regs->sp;
+ struct thread_info *tinfo;
+
+ if (context == (sp & ~(THREAD_SIZE - 1)))
+ return sp;
+
+ tinfo = (struct thread_info *)context;
+ if (tinfo->previous_esp)
+ return tinfo->previous_esp;
+
+ return (unsigned long)regs;
+}
+EXPORT_SYMBOL_GPL(kernel_stack_pointer);
+
static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
{
BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
@@ -1511,6 +1541,13 @@ void syscall_trace_leave(struct pt_regs *regs)
{
bool step;
+ /*
+ * We may come here right after calling schedule_user()
+ * or do_notify_resume(), in which case we can be in RCU
+ * user mode.
+ */
+ rcu_user_exit();
+
audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index c80a33bc528b..f3e2ec878b8c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -68,6 +68,8 @@
#include <asm/mwait.h>
#include <asm/apic.h>
#include <asm/io_apic.h>
+#include <asm/i387.h>
+#include <asm/fpu-internal.h>
#include <asm/setup.h>
#include <asm/uv/uv.h>
#include <linux/mc146818rtc.h>
@@ -818,6 +820,9 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+ /* the FPU context is blank, nobody can own it */
+ __cpu_disable_lazy_restore(cpu);
+
err = do_boot_cpu(apicid, cpu, tidle);
if (err) {
pr_debug("do_boot_cpu failed %d\n", err);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 39171cb307ea..bba39bfa1c4b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -426,8 +426,7 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
_ASM_EXTABLE(1b, 3b) \
: "=m" ((ctxt)->eflags), "=&r" (_tmp), \
"+a" (*rax), "+d" (*rdx), "+qm"(_ex) \
- : "i" (EFLAGS_MASK), "m" ((ctxt)->src.val), \
- "a" (*rax), "d" (*rdx)); \
+ : "i" (EFLAGS_MASK), "m" ((ctxt)->src.val)); \
} while (0)
/* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 0777f042e400..60f926cd8b0e 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
}
if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
- || vmflag == VM_HUGETLB) {
+ || vmflag & VM_HUGETLB) {
local_flush_tlb();
goto flush_all;
}
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 41bd2a2d2c50..b914e20b5a00 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
reg_read(reg, value);
}
+static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&pci_config_lock, flags);
+ /* force interrupt pin value to 0 */
+ *value = reg->sim_reg.value & 0xfff00ff;
+ raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
static struct sim_dev_reg bus1_fixups[] = {
DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
@@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = {
DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+ DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
@@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = {
DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+ DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+ DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
};
static void __init init_sim_regs(void)
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index 4c61b52191eb..92525cb8e54c 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -21,12 +21,25 @@
#include <asm/i8259.h>
#include <asm/io.h>
#include <asm/io_apic.h>
+#include <asm/emergency-restart.h>
static int ce4100_i8042_detect(void)
{
return 0;
}
+/*
+ * The CE4100 platform has an internal 8051 Microcontroller which is
+ * responsible for signaling to the external Power Management Unit the
+ * intention to reset, reboot or power off the system. This 8051 device has
+ * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
+ * to power off the system.
+ */
+static void ce4100_power_off(void)
+{
+ outb(0x4, 0xcf9);
+}
+
#ifdef CONFIG_SERIAL_8250
static unsigned int mem_serial_in(struct uart_port *p, int offset)
@@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void)
x86_init.mpparse.find_smp_config = x86_init_noop;
x86_init.pci.init = ce4100_pci_init;
+ /*
+ * By default, the reboot method is ACPI which is supported by the
+ * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
+ * the bootloader will however issue a system power off instead of
+ * reboot. By using BOOT_KBD we ensure proper system reboot as
+ * expected.
+ */
+ reboot_type = BOOT_KBD;
+
#ifdef CONFIG_X86_IO_APIC
x86_init.pci.init_irq = sdv_pci_init;
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
#endif
+
+ pm_power_off = ce4100_power_off;
}
diff --git a/block/blk-exec.c b/block/blk-exec.c
index 8b6dc5bd4dd0..f71eac35c1b9 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
rq_end_io_fn *done)
{
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+ bool is_pm_resume;
WARN_ON(irqs_disabled());
rq->rq_disk = bd_disk;
rq->end_io = done;
+ /*
+ * need to check this before __blk_run_queue(), because rq can
+ * be freed before that returns.
+ */
+ is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
spin_lock_irq(q->queue_lock);
@@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
__elv_add_request(q, rq, where);
__blk_run_queue(q);
/* the queue is stopped so it won't be run */
- if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+ if (is_pm_resume)
q->request_fn(q);
spin_unlock_irq(q->queue_lock);
}
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 119d58db8342..0300bf612946 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -181,6 +181,12 @@ config ACPI_DOCK
This driver supports ACPI-controlled docking stations and removable
drive bays such as the IBM Ultrabay and the Dell Module Bay.
+config ACPI_I2C
+ def_tristate I2C
+ depends on I2C
+ help
+ ACPI I2C enumeration support.
+
config ACPI_PROCESSOR
tristate "Processor"
select THERMAL
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 82422fe90f81..2a4502becd13 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -21,9 +21,10 @@ obj-y += acpi.o \
acpi-y += osl.o utils.o reboot.o
acpi-y += nvs.o
-# sleep related files
+# Power management related files
acpi-y += wakeup.o
acpi-y += sleep.o
+acpi-$(CONFIG_PM) += device_pm.o
acpi-$(CONFIG_ACPI_SLEEP) += proc.o
@@ -32,10 +33,12 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o
#
acpi-y += bus.o glue.o
acpi-y += scan.o
+acpi-y += resource.o
acpi-y += processor_core.o
acpi-y += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
+acpi-y += acpi_platform.o
acpi-y += power.o
acpi-y += event.o
acpi-y += sysfs.o
@@ -67,6 +70,7 @@ obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
+obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o
diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c
new file mode 100644
index 000000000000..82045e3f5cac
--- /dev/null
+++ b/drivers/acpi/acpi_i2c.c
@@ -0,0 +1,103 @@
+/*
+ * ACPI I2C enumeration support
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.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/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/i2c.h>
+#include <linux/ioport.h>
+
+ACPI_MODULE_NAME("i2c");
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+ struct i2c_board_info *info = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ struct acpi_resource_i2c_serialbus *sb;
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ info->addr = sb->slave_address;
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ info->flags |= I2C_CLIENT_TEN;
+ }
+ } else if (info->irq < 0) {
+ struct resource r;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &r))
+ info->irq = r.start;
+ }
+
+ /* Tell the ACPI core to skip this resource */
+ return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+ void *data, void **return_value)
+{
+ struct i2c_adapter *adapter = data;
+ struct list_head resource_list;
+ struct i2c_board_info info;
+ struct acpi_device *adev;
+ int ret;
+
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+ if (acpi_bus_get_status(adev) || !adev->status.present)
+ return AE_OK;
+
+ memset(&info, 0, sizeof(info));
+ info.acpi_node.handle = handle;
+ info.irq = -1;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ acpi_i2c_add_resource, &info);
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (ret < 0 || !info.addr)
+ return AE_OK;
+
+ strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+ if (!i2c_new_device(adapter, &info)) {
+ dev_err(&adapter->dev,
+ "failed to add I2C device %s from ACPI\n",
+ dev_name(&adev->dev));
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adapter: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+void acpi_i2c_register_devices(struct i2c_adapter *adapter)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ handle = ACPI_HANDLE(&adapter->dev);
+ if (!handle)
+ return;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_i2c_add_device, NULL,
+ adapter, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
+}
+EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 24c807f96636..eb30e5ab4cab 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/memory_hotplug.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
#include <acpi/acpi_drivers.h>
#define ACPI_MEMORY_DEVICE_CLASS "memory"
@@ -78,6 +79,7 @@ struct acpi_memory_info {
unsigned short caching; /* memory cache attribute */
unsigned short write_protect; /* memory read/write attribute */
unsigned int enabled:1;
+ unsigned int failed:1;
};
struct acpi_memory_device {
@@ -86,8 +88,6 @@ struct acpi_memory_device {
struct list_head res_list;
};
-static int acpi_hotmem_initialized;
-
static acpi_status
acpi_memory_get_resource(struct acpi_resource *resource, void *context)
{
@@ -125,12 +125,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
return AE_OK;
}
+static void
+acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
+{
+ struct acpi_memory_info *info, *n;
+
+ list_for_each_entry_safe(info, n, &mem_device->res_list, list)
+ kfree(info);
+ INIT_LIST_HEAD(&mem_device->res_list);
+}
+
static int
acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
{
acpi_status status;
- struct acpi_memory_info *info, *n;
-
if (!list_empty(&mem_device->res_list))
return 0;
@@ -138,9 +146,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
acpi_memory_get_resource, mem_device);
if (ACPI_FAILURE(status)) {
- list_for_each_entry_safe(info, n, &mem_device->res_list, list)
- kfree(info);
- INIT_LIST_HEAD(&mem_device->res_list);
+ acpi_memory_free_device_resources(mem_device);
return -EINVAL;
}
@@ -170,7 +176,7 @@ acpi_memory_get_device(acpi_handle handle,
/* Get the parent device */
result = acpi_bus_get_device(phandle, &pdevice);
if (result) {
- printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
+ acpi_handle_warn(phandle, "Cannot get acpi bus device\n");
return -EINVAL;
}
@@ -180,14 +186,14 @@ acpi_memory_get_device(acpi_handle handle,
*/
result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
if (result) {
- printk(KERN_WARNING PREFIX "Cannot add acpi bus");
+ acpi_handle_warn(handle, "Cannot add acpi bus\n");
return -EINVAL;
}
end:
*mem_device = acpi_driver_data(device);
if (!(*mem_device)) {
- printk(KERN_ERR "\n driver data not found");
+ dev_err(&device->dev, "driver data not found\n");
return -ENODEV;
}
@@ -224,7 +230,8 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
/* Get the range from the _CRS */
result = acpi_memory_get_device_resources(mem_device);
if (result) {
- printk(KERN_ERR PREFIX "get_device_resources failed\n");
+ dev_err(&mem_device->device->dev,
+ "get_device_resources failed\n");
mem_device->state = MEMORY_INVALID_STATE;
return result;
}
@@ -251,13 +258,27 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
node = memory_add_physaddr_to_nid(info->start_addr);
result = add_memory(node, info->start_addr, info->length);
- if (result)
+
+ /*
+ * If the memory block has been used by the kernel, add_memory()
+ * returns -EEXIST. If add_memory() returns the other error, it
+ * means that this memory block is not used by the kernel.
+ */
+ if (result && result != -EEXIST) {
+ info->failed = 1;
continue;
- info->enabled = 1;
+ }
+
+ if (!result)
+ info->enabled = 1;
+ /*
+ * Add num_enable even if add_memory() returns -EEXIST, so the
+ * device is bound to this driver.
+ */
num_enabled++;
}
if (!num_enabled) {
- printk(KERN_ERR PREFIX "add_memory failed\n");
+ dev_err(&mem_device->device->dev, "add_memory failed\n");
mem_device->state = MEMORY_INVALID_STATE;
return -EINVAL;
}
@@ -272,68 +293,31 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
return 0;
}
-static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
{
- acpi_status status;
- struct acpi_object_list arg_list;
- union acpi_object arg;
- unsigned long long current_status;
-
-
- /* Issue the _EJ0 command */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = 1;
- status = acpi_evaluate_object(mem_device->device->handle,
- "_EJ0", &arg_list, NULL);
- /* Return on _EJ0 failure */
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "_EJ0 failed"));
- return -ENODEV;
- }
-
- /* Evalute _STA to check if the device is disabled */
- status = acpi_evaluate_integer(mem_device->device->handle, "_STA",
- NULL, &current_status);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- /* Check for device status. Device should be disabled */
- if (current_status & ACPI_STA_DEVICE_ENABLED)
- return -EINVAL;
+ int result = 0;
+ struct acpi_memory_info *info, *n;
- return 0;
-}
+ list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
+ if (info->failed)
+ /* The kernel does not use this memory block */
+ continue;
-static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
-{
- int result;
- struct acpi_memory_info *info, *n;
+ if (!info->enabled)
+ /*
+ * The kernel uses this memory block, but it may be not
+ * managed by us.
+ */
+ return -EBUSY;
+ result = remove_memory(info->start_addr, info->length);
+ if (result)
+ return result;
- /*
- * Ask the VM to offline this memory range.
- * Note: Assume that this function returns zero on success
- */
- list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
- if (info->enabled) {
- result = remove_memory(info->start_addr, info->length);
- if (result)
- return result;
- }
+ list_del(&info->list);
kfree(info);
}
- /* Power-off and eject the device */
- result = acpi_memory_powerdown_device(mem_device);
- if (result) {
- /* Set the status of the device to invalid */
- mem_device->state = MEMORY_INVALID_STATE;
- return result;
- }
-
- mem_device->state = MEMORY_POWER_OFF_STATE;
return result;
}
@@ -341,6 +325,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_memory_device *mem_device;
struct acpi_device *device;
+ struct acpi_eject_event *ej_event = NULL;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
switch (event) {
@@ -353,7 +338,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"\nReceived DEVICE CHECK notification for device\n"));
if (acpi_memory_get_device(handle, &mem_device)) {
- printk(KERN_ERR PREFIX "Cannot find driver data\n");
+ acpi_handle_err(handle, "Cannot find driver data\n");
break;
}
@@ -361,7 +346,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
break;
if (acpi_memory_enable_device(mem_device)) {
- printk(KERN_ERR PREFIX "Cannot enable memory device\n");
+ acpi_handle_err(handle,"Cannot enable memory device\n");
break;
}
@@ -373,40 +358,28 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
"\nReceived EJECT REQUEST notification for device\n"));
if (acpi_bus_get_device(handle, &device)) {
- printk(KERN_ERR PREFIX "Device doesn't exist\n");
+ acpi_handle_err(handle, "Device doesn't exist\n");
break;
}
mem_device = acpi_driver_data(device);
if (!mem_device) {
- printk(KERN_ERR PREFIX "Driver Data is NULL\n");
+ acpi_handle_err(handle, "Driver Data is NULL\n");
break;
}
- /*
- * Currently disabling memory device from kernel mode
- * TBD: Can also be disabled from user mode scripts
- * TBD: Can also be disabled by Callback registration
- * with generic sysfs driver
- */
- if (acpi_memory_disable_device(mem_device)) {
- printk(KERN_ERR PREFIX "Disable memory device\n");
- /*
- * If _EJ0 was called but failed, _OST is not
- * necessary.
- */
- if (mem_device->state == MEMORY_INVALID_STATE)
- return;
-
+ ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+ if (!ej_event) {
+ pr_err(PREFIX "No memory, dropping EJECT\n");
break;
}
- /*
- * TBD: Invoke acpi_bus_remove to cleanup data structures
- */
+ ej_event->handle = handle;
+ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+ acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+ (void *)ej_event);
- /* _EJ0 succeeded; _OST is not necessary */
+ /* eject is performed asynchronously */
return;
-
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Unsupported event [0x%x]\n", event));
@@ -420,6 +393,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
return;
}
+static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
+{
+ if (!mem_device)
+ return;
+
+ acpi_memory_free_device_resources(mem_device);
+ kfree(mem_device);
+}
+
static int acpi_memory_device_add(struct acpi_device *device)
{
int result;
@@ -449,23 +431,16 @@ static int acpi_memory_device_add(struct acpi_device *device)
/* Set the device state */
mem_device->state = MEMORY_POWER_ON_STATE;
- printk(KERN_DEBUG "%s \n", acpi_device_name(device));
-
- /*
- * Early boot code has recognized memory area by EFI/E820.
- * If DSDT shows these memory devices on boot, hotplug is not necessary
- * for them. So, it just returns until completion of this driver's
- * start up.
- */
- if (!acpi_hotmem_initialized)
- return 0;
+ pr_debug("%s\n", acpi_device_name(device));
if (!acpi_memory_check_device(mem_device)) {
/* call add_memory func */
result = acpi_memory_enable_device(mem_device);
- if (result)
- printk(KERN_ERR PREFIX
+ if (result) {
+ dev_err(&device->dev,
"Error in acpi_memory_enable_device\n");
+ acpi_memory_device_free(mem_device);
+ }
}
return result;
}
@@ -473,13 +448,18 @@ static int acpi_memory_device_add(struct acpi_device *device)
static int acpi_memory_device_remove(struct acpi_device *device, int type)
{
struct acpi_memory_device *mem_device = NULL;
-
+ int result;
if (!device || !acpi_driver_data(device))
return -EINVAL;
mem_device = acpi_driver_data(device);
- kfree(mem_device);
+
+ result = acpi_memory_remove_memory(mem_device);
+ if (result)
+ return result;
+
+ acpi_memory_device_free(mem_device);
return 0;
}
@@ -568,7 +548,6 @@ static int __init acpi_memory_device_init(void)
return -ENODEV;
}
- acpi_hotmem_initialized = 1;
return 0;
}
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index af4aad6ee2eb..16fa979f7180 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -286,7 +286,7 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long num;
- if (strict_strtoul(buf, 0, &num))
+ if (kstrtoul(buf, 0, &num))
return -EINVAL;
if (num < 1 || num >= 100)
return -EINVAL;
@@ -309,7 +309,7 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long num;
- if (strict_strtoul(buf, 0, &num))
+ if (kstrtoul(buf, 0, &num))
return -EINVAL;
if (num < 1 || num >= 100)
return -EINVAL;
@@ -332,7 +332,7 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long num;
- if (strict_strtoul(buf, 0, &num))
+ if (kstrtoul(buf, 0, &num))
return -EINVAL;
mutex_lock(&isolated_cpus_lock);
acpi_pad_idle_cpus(num);
@@ -457,7 +457,7 @@ static void acpi_pad_notify(acpi_handle handle, u32 event,
dev_name(&device->dev), event, 0);
break;
default:
- printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
+ pr_warn("Unsupported event [0x%x]\n", event);
break;
}
}
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
new file mode 100644
index 000000000000..db129b9f52cb
--- /dev/null
+++ b/drivers/acpi/acpi_platform.c
@@ -0,0 +1,104 @@
+/*
+ * ACPI support for platform bus type.
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ * Mathias Nyman <mathias.nyman@linux.intel.com>
+ * Rafael J. Wysocki <rafael.j.wysocki@intel.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/acpi.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "internal.h"
+
+ACPI_MODULE_NAME("platform");
+
+/**
+ * acpi_create_platform_device - Create platform device for ACPI device node
+ * @adev: ACPI device node to create a platform device for.
+ *
+ * Check if the given @adev can be represented as a platform device and, if
+ * that's the case, create and register a platform device, populate its common
+ * resources and returns a pointer to it. Otherwise, return %NULL.
+ *
+ * The platform device's name will be taken from the @adev's _HID and _UID.
+ */
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
+{
+ struct platform_device *pdev = NULL;
+ struct acpi_device *acpi_parent;
+ struct platform_device_info pdevinfo;
+ struct resource_list_entry *rentry;
+ struct list_head resource_list;
+ struct resource *resources;
+ int count;
+
+ /* If the ACPI node already has a physical device attached, skip it. */
+ if (adev->physical_node_count)
+ return NULL;
+
+ INIT_LIST_HEAD(&resource_list);
+ count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+ if (count <= 0)
+ return NULL;
+
+ resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
+ if (!resources) {
+ dev_err(&adev->dev, "No memory for resources\n");
+ acpi_dev_free_resource_list(&resource_list);
+ return NULL;
+ }
+ count = 0;
+ list_for_each_entry(rentry, &resource_list, node)
+ resources[count++] = rentry->res;
+
+ acpi_dev_free_resource_list(&resource_list);
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ /*
+ * If the ACPI node has a parent and that parent has a physical device
+ * attached to it, that physical device should be the parent of the
+ * platform device we are about to create.
+ */
+ pdevinfo.parent = NULL;
+ acpi_parent = adev->parent;
+ if (acpi_parent) {
+ struct acpi_device_physical_node *entry;
+ struct list_head *list;
+
+ mutex_lock(&acpi_parent->physical_node_lock);
+ list = &acpi_parent->physical_node_list;
+ if (!list_empty(list)) {
+ entry = list_first_entry(list,
+ struct acpi_device_physical_node,
+ node);
+ pdevinfo.parent = entry->dev;
+ }
+ mutex_unlock(&acpi_parent->physical_node_lock);
+ }
+ pdevinfo.name = dev_name(&adev->dev);
+ pdevinfo.id = -1;
+ pdevinfo.res = resources;
+ pdevinfo.num_res = count;
+ pdevinfo.acpi_node.handle = adev->handle;
+ pdev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(pdev)) {
+ dev_err(&adev->dev, "platform device creation failed: %ld\n",
+ PTR_ERR(pdev));
+ pdev = NULL;
+ } else {
+ dev_dbg(&adev->dev, "created platform device %s\n",
+ dev_name(&pdev->dev));
+ }
+
+ kfree(resources);
+ return pdev;
+}
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 7f1d40797e80..c8bc24bd1f72 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -161,3 +161,6 @@ acpi-y += \
utxfinit.o \
utxferror.o \
utxfmutex.o
+
+acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o utclib.o
+
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 5e8abb07724f..432a318c9ed1 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -44,17 +44,28 @@
#ifndef __ACDEBUG_H__
#define __ACDEBUG_H__
-#define ACPI_DEBUG_BUFFER_SIZE 4196
+#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
-struct command_info {
+struct acpi_db_command_info {
char *name; /* Command Name */
u8 min_args; /* Minimum arguments required */
};
-struct argument_info {
+struct acpi_db_command_help {
+ u8 line_count; /* Number of help lines */
+ char *invocation; /* Command Invocation */
+ char *description; /* Command Description */
+};
+
+struct acpi_db_argument_info {
char *name; /* Argument Name */
};
+struct acpi_db_execute_walk {
+ u32 count;
+ u32 max_count;
+};
+
#define PARAM_LIST(pl) pl
#define DBTEST_OUTPUT_LEVEL(lvl) if (acpi_gbl_db_opt_verbose)
#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\
@@ -77,59 +88,71 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
/*
* dbcmds - debug commands and output routines
*/
-acpi_status acpi_db_disassemble_method(char *name);
+struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string);
void acpi_db_display_table_info(char *table_arg);
-void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg);
+void acpi_db_display_template(char *buffer_arg);
-void
-acpi_db_set_method_breakpoint(char *location,
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op);
+void acpi_db_unload_acpi_table(char *name);
-void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
+void acpi_db_send_notify(char *name, u32 value);
-void acpi_db_get_bus_info(void);
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
-void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
+acpi_status acpi_db_sleep(char *object_arg);
-void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
+void acpi_db_display_locks(void);
-void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
+void acpi_db_display_resources(char *object_arg);
-void acpi_db_send_notify(char *name, u32 value);
+ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+
+void acpi_db_display_handlers(void);
+
+ACPI_HW_DEPENDENT_RETURN_VOID(void
+ acpi_db_generate_gpe(char *gpe_arg,
+ char *block_arg))
+
+/*
+ * dbmethod - control method commands
+ */
+void
+acpi_db_set_method_breakpoint(char *location,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op);
+
+void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
-acpi_status
-acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
+acpi_status acpi_db_disassemble_method(char *name);
-void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
+void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
-acpi_status acpi_db_find_name_in_namespace(char *name_arg);
+void acpi_db_batch_execute(char *count_arg);
+/*
+ * dbnames - namespace commands
+ */
void acpi_db_set_scope(char *name);
-ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_db_sleep(char *object_arg))
+void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
-void acpi_db_find_references(char *object_arg);
+void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
-void acpi_db_display_locks(void);
+acpi_status acpi_db_find_name_in_namespace(char *name_arg);
-void acpi_db_display_resources(char *object_arg);
+void acpi_db_check_predefined_names(void);
-ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+acpi_status
+acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
void acpi_db_check_integrity(void);
-ACPI_HW_DEPENDENT_RETURN_VOID(void
- acpi_db_generate_gpe(char *gpe_arg,
- char *block_arg))
-
-void acpi_db_check_predefined_names(void);
+void acpi_db_find_references(char *object_arg);
-void acpi_db_batch_execute(void);
+void acpi_db_get_bus_info(void);
/*
* dbdisply - debug display commands
@@ -161,7 +184,8 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
/*
* dbexec - debugger control method execution
*/
-void acpi_db_execute(char *name, char **args, u32 flags);
+void
+acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags);
void
acpi_db_create_execution_threads(char *num_threads_arg,
@@ -175,7 +199,8 @@ u32 acpi_db_get_cache_info(struct acpi_memory_list *cache);
* dbfileio - Debugger file I/O commands
*/
acpi_object_type
-acpi_db_match_argument(char *user_argument, struct argument_info *arguments);
+acpi_db_match_argument(char *user_argument,
+ struct acpi_db_argument_info *arguments);
void acpi_db_close_debug_file(void);
@@ -208,6 +233,11 @@ acpi_db_command_dispatch(char *input_buffer,
void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
+acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
+
+char *acpi_db_get_next_token(char *string,
+ char **next, acpi_object_type * return_type);
+
/*
* dbstats - Generation and display of ACPI table statistics
*/
diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 5935ba6707e2..ed33ebcdaebe 100644
--- a/drivers/acpi/acpica/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
@@ -309,10 +309,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state);
acpi_status
acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
- *origin, union acpi_operand_object
- *mth_desc, struct acpi_thread_state
- *thread);
+struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id,
+ union acpi_parse_object
+ *origin,
+ union acpi_operand_object
+ *mth_desc,
+ struct acpi_thread_state
+ *thread);
acpi_status
acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index c0a43b38c6a3..e975c6720448 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -84,9 +84,11 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index ce79100fb5eb..64472e4ec329 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -70,7 +70,7 @@
/*
* Enable "slack" in the AML interpreter? Default is FALSE, and the
- * interpreter strictly follows the ACPI specification. Setting to TRUE
+ * interpreter strictly follows the ACPI specification. Setting to TRUE
* allows the interpreter to ignore certain errors and/or bad AML constructs.
*
* Currently, these features are enabled by this flag:
@@ -155,26 +155,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE);
/*****************************************************************************
*
- * Debug support
- *
- ****************************************************************************/
-
-/* Procedure nesting level for debug output */
-
-extern u32 acpi_gbl_nesting_level;
-
-ACPI_EXTERN u32 acpi_gpe_count;
-ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
-
-/* Support for dynamic control method tracing mechanism */
-
-ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
-
-/*****************************************************************************
- *
* ACPI Table globals
*
****************************************************************************/
@@ -259,15 +239,6 @@ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock; /* For ACPI H/W except GPE reg
*
****************************************************************************/
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-
-/* Lists for tracking memory allocations */
-
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
-ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
-#endif
-
/* Object caches */
ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache;
@@ -326,6 +297,15 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
#endif
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+/* Lists for tracking memory allocations */
+
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
+ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
+#endif
+
/*****************************************************************************
*
* Namespace globals
@@ -396,13 +376,35 @@ ACPI_EXTERN struct acpi_gpe_block_info
#if (!ACPI_REDUCED_HARDWARE)
ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
-ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
+ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler;
ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
#endif /* !ACPI_REDUCED_HARDWARE */
/*****************************************************************************
*
+ * Debug support
+ *
+ ****************************************************************************/
+
+/* Procedure nesting level for debug output */
+
+extern u32 acpi_gbl_nesting_level;
+
+/* Event counters */
+
+ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+
+/* Support for dynamic control method tracing mechanism */
+
+ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
+
+/*****************************************************************************
+ *
* Debugger globals
*
****************************************************************************/
@@ -426,10 +428,11 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[80];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[80];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[40];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[40];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
ACPI_EXTERN char *acpi_gbl_db_buffer;
ACPI_EXTERN char *acpi_gbl_db_filename;
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index c816ee675094..ff8bd0061e8b 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -262,10 +262,10 @@ struct acpi_create_field_info {
};
typedef
-acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
+acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
/*
- * Bitmapped ACPI types. Used internally only
+ * Bitmapped ACPI types. Used internally only
*/
#define ACPI_BTYPE_ANY 0x00000000
#define ACPI_BTYPE_INTEGER 0x00000001
@@ -486,8 +486,10 @@ struct acpi_gpe_device_info {
struct acpi_namespace_node *gpe_device;
};
-typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block, void *context);
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
+ gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block,
+ void *context);
/* Information about each particular fixed event */
@@ -582,7 +584,7 @@ struct acpi_pscope_state {
};
/*
- * Thread state - one per thread across multiple walk states. Multiple walk
+ * Thread state - one per thread across multiple walk states. Multiple walk
* states are created when there are nested control methods executing.
*/
struct acpi_thread_state {
@@ -645,7 +647,7 @@ union acpi_generic_state {
*
****************************************************************************/
-typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
+typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state);
/* Address Range info block */
@@ -1031,6 +1033,7 @@ struct acpi_db_method_info {
acpi_handle method;
acpi_handle main_thread_gate;
acpi_handle thread_complete_gate;
+ acpi_handle info_gate;
acpi_thread_id *threads;
u32 num_threads;
u32 num_created;
@@ -1041,6 +1044,7 @@ struct acpi_db_method_info {
u32 num_loops;
char pathname[128];
char **args;
+ acpi_object_type *types;
/*
* Arguments to be passed to method for the command
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index a7f68c47f517..5efad99f2169 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -84,29 +84,29 @@
/* These macros reverse the bytes during the move, converting little-endian to big endian */
- /* Big Endian <== Little Endian */
- /* Hi...Lo Lo...Hi */
+ /* Big Endian <== Little Endian */
+ /* Hi...Lo Lo...Hi */
/* 16-bit source, 16/32/64 destination */
#define ACPI_MOVE_16_TO_16(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
- (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
+ (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_16_TO_32(d, s) {(*(u32 *)(void *)(d))=0;\
- ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
- ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+ ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+ ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_16_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
- ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
- ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
+ ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
+ ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
/* 32-bit source, 16/32/64 destination */
#define ACPI_MOVE_32_TO_16(d, s) ACPI_MOVE_16_TO_16(d, s) /* Truncate to 16 */
#define ACPI_MOVE_32_TO_32(d, s) {(( u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
- (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
- (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
- (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+ (( u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
+ (( u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+ (( u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
#define ACPI_MOVE_32_TO_64(d, s) {(*(u64 *)(void *)(d))=0;\
((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
@@ -196,24 +196,12 @@
#endif
#endif
-/* Macros based on machine integer width */
-
-#if ACPI_MACHINE_WIDTH == 32
-#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_32_TO_16(d, s)
-
-#elif ACPI_MACHINE_WIDTH == 64
-#define ACPI_MOVE_SIZE_TO_16(d, s) ACPI_MOVE_64_TO_16(d, s)
-
-#else
-#error unknown ACPI_MACHINE_WIDTH
-#endif
-
/*
* Fast power-of-two math macros for non-optimized compilers
*/
-#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2)))
-#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2)))
-#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1)))
+#define _ACPI_DIV(value, power_of2) ((u32) ((value) >> (power_of2)))
+#define _ACPI_MUL(value, power_of2) ((u32) ((value) << (power_of2)))
+#define _ACPI_MOD(value, divisor) ((u32) ((value) & ((divisor) -1)))
#define ACPI_DIV_2(a) _ACPI_DIV(a, 1)
#define ACPI_MUL_2(a) _ACPI_MUL(a, 1)
@@ -238,12 +226,12 @@
/*
* Rounding macros (Power of two boundaries only)
*/
-#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \
- (~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_DOWN(value, boundary) (((acpi_size)(value)) & \
+ (~(((acpi_size) boundary)-1)))
-#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \
- (((acpi_size) boundary)-1)) & \
- (~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_UP(value, boundary) ((((acpi_size)(value)) + \
+ (((acpi_size) boundary)-1)) & \
+ (~(((acpi_size) boundary)-1)))
/* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */
@@ -264,7 +252,7 @@
#define ACPI_ROUND_UP_TO(value, boundary) (((value) + ((boundary)-1)) / (boundary))
-#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1))
+#define ACPI_IS_MISALIGNED(value) (((acpi_size) value) & (sizeof(acpi_size)-1))
/*
* Bitmask creation
@@ -355,7 +343,6 @@
* Ascii error messages can be configured out
*/
#ifndef ACPI_NO_ERROR_MESSAGES
-
/*
* Error reporting. Callers module and line number are inserted by AE_INFO,
* the plist contains a set of parens to allow variable-length lists.
@@ -375,18 +362,15 @@
#define ACPI_WARN_PREDEFINED(plist)
#define ACPI_INFO_PREDEFINED(plist)
-#endif /* ACPI_NO_ERROR_MESSAGES */
+#endif /* ACPI_NO_ERROR_MESSAGES */
/*
* Debug macros that are conditionally compiled
*/
#ifdef ACPI_DEBUG_OUTPUT
-
/*
* Function entry tracing
*/
-#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE
-
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
#define ACPI_FUNCTION_TRACE_PTR(a, b) ACPI_FUNCTION_NAME(a) \
@@ -464,45 +448,19 @@
#endif /* ACPI_SIMPLE_RETURN_MACROS */
-#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_TRACE_PTR(a,b)
-#define ACPI_FUNCTION_TRACE_U32(a,b)
-#define ACPI_FUNCTION_TRACE_STR(a,b)
-#define ACPI_FUNCTION_EXIT
-#define ACPI_FUNCTION_STATUS_EXIT(s)
-#define ACPI_FUNCTION_VALUE_EXIT(s)
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_ENTRY()
-
-#define return_VOID return
-#define return_ACPI_STATUS(s) return(s)
-#define return_VALUE(s) return(s)
-#define return_UINT8(s) return(s)
-#define return_UINT32(s) return(s)
-#define return_PTR(s) return(s)
-
-#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
/* Conditional execution */
#define ACPI_DEBUG_EXEC(a) a
-#define ACPI_NORMAL_EXEC(a)
-
-#define ACPI_DEBUG_DEFINE(a) a;
#define ACPI_DEBUG_ONLY_MEMBERS(a) a;
#define _VERBOSE_STRUCTURES
-/* Stack and buffer dumping */
+/* Various object display routines for debug */
#define ACPI_DUMP_STACK_ENTRY(a) acpi_ex_dump_operand((a), 0)
-#define ACPI_DUMP_OPERANDS(a, b, c) acpi_ex_dump_operands(a, b, c)
-
+#define ACPI_DUMP_OPERANDS(a, b ,c) acpi_ex_dump_operands(a, b, c)
#define ACPI_DUMP_ENTRY(a, b) acpi_ns_dump_entry (a, b)
#define ACPI_DUMP_PATHNAME(a, b, c, d) acpi_ns_dump_pathname(a, b, c, d)
-#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a)
-#define ACPI_DUMP_BUFFER(a, b) acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
+#define ACPI_DUMP_BUFFER(a, b) acpi_ut_debug_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
#else
/*
@@ -510,25 +468,23 @@
* leaving no executable debug code!
*/
#define ACPI_DEBUG_EXEC(a)
-#define ACPI_NORMAL_EXEC(a) a;
-
-#define ACPI_DEBUG_DEFINE(a) do { } while(0)
-#define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0)
-#define ACPI_FUNCTION_TRACE(a) do { } while(0)
-#define ACPI_FUNCTION_TRACE_PTR(a, b) do { } while(0)
-#define ACPI_FUNCTION_TRACE_U32(a, b) do { } while(0)
-#define ACPI_FUNCTION_TRACE_STR(a, b) do { } while(0)
-#define ACPI_FUNCTION_EXIT do { } while(0)
-#define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0)
-#define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0)
-#define ACPI_FUNCTION_ENTRY() do { } while(0)
-#define ACPI_DUMP_STACK_ENTRY(a) do { } while(0)
-#define ACPI_DUMP_OPERANDS(a, b, c) do { } while(0)
-#define ACPI_DUMP_ENTRY(a, b) do { } while(0)
-#define ACPI_DUMP_TABLES(a, b) do { } while(0)
-#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0)
-#define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0)
-#define ACPI_DUMP_BUFFER(a, b) do { } while(0)
+#define ACPI_DEBUG_ONLY_MEMBERS(a)
+#define ACPI_FUNCTION_TRACE(a)
+#define ACPI_FUNCTION_TRACE_PTR(a, b)
+#define ACPI_FUNCTION_TRACE_U32(a, b)
+#define ACPI_FUNCTION_TRACE_STR(a, b)
+#define ACPI_FUNCTION_EXIT
+#define ACPI_FUNCTION_STATUS_EXIT(s)
+#define ACPI_FUNCTION_VALUE_EXIT(s)
+#define ACPI_FUNCTION_ENTRY()
+#define ACPI_DUMP_STACK_ENTRY(a)
+#define ACPI_DUMP_OPERANDS(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b)
+#define ACPI_DUMP_TABLES(a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b)
+#define ACPI_DEBUG_PRINT(pl)
+#define ACPI_DEBUG_PRINT_RAW(pl)
#define return_VOID return
#define return_ACPI_STATUS(s) return(s)
@@ -556,18 +512,6 @@
#define ACPI_DEBUGGER_EXEC(a)
#endif
-#ifdef ACPI_DEBUG_OUTPUT
-/*
- * 1) Set name to blanks
- * 2) Copy the object name
- */
-#define ACPI_ADD_OBJECT_NAME(a,b) ACPI_MEMSET (a->common.name, ' ', sizeof (a->common.name));\
- ACPI_STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name))
-#else
-
-#define ACPI_ADD_OBJECT_NAME(a,b)
-#endif
-
/*
* Memory allocation tracking (DEBUG ONLY)
*/
@@ -578,13 +522,13 @@
/* Memory allocation */
#ifndef ACPI_ALLOCATE
-#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a) acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS)
#endif
#ifndef ACPI_ALLOCATE_ZEROED
-#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS)
#endif
#ifndef ACPI_FREE
-#define ACPI_FREE(a) acpio_os_free(a)
+#define ACPI_FREE(a) acpi_os_free(a)
#endif
#define ACPI_MEM_TRACKING(a)
@@ -592,16 +536,25 @@
/* Memory allocation */
-#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
-#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a) acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
#define ACPI_FREE(a) acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS)
#define ACPI_MEM_TRACKING(a) a
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
-/* Preemption point */
-#ifndef ACPI_PREEMPTION_POINT
-#define ACPI_PREEMPTION_POINT() /* no preemption */
-#endif
+/*
+ * Macros used for ACPICA utilities only
+ */
+
+/* Generate a UUID */
+
+#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
+ (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
+ (b) & 0xFF, ((b) >> 8) & 0xFF, \
+ (c) & 0xFF, ((c) >> 8) & 0xFF, \
+ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
+
+#define ACPI_IS_OCTAL_DIGIT(d) (((char)(d) >= '0') && ((char)(d) <= '7'))
#endif /* ACMACROS_H */
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 364a1303fb8f..24eb9eac9514 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Name: acobject.h - Definition of union acpi_operand_object (Internal object only)
@@ -179,7 +178,7 @@ struct acpi_object_method {
union acpi_operand_object *mutex;
u8 *aml_start;
union {
- ACPI_INTERNAL_METHOD implementation;
+ acpi_internal_method implementation;
union acpi_operand_object *handler;
} dispatch;
@@ -198,7 +197,7 @@ struct acpi_object_method {
/******************************************************************************
*
- * Objects that can be notified. All share a common notify_info area.
+ * Objects that can be notified. All share a common notify_info area.
*
*****************************************************************************/
@@ -235,7 +234,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
/******************************************************************************
*
- * Fields. All share a common header/info field.
+ * Fields. All share a common header/info field.
*
*****************************************************************************/
diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h
index 9440d053fbb3..d786a5128b78 100644
--- a/drivers/acpi/acpica/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
@@ -54,7 +54,7 @@
#define _UNK 0x6B
/*
- * Reserved ASCII characters. Do not use any of these for
+ * Reserved ASCII characters. Do not use any of these for
* internal opcodes, since they are used to differentiate
* name strings from AML opcodes
*/
@@ -63,7 +63,7 @@
#define _PFX 0x6D
/*
- * All AML opcodes and the parse-time arguments for each. Used by the AML
+ * All AML opcodes and the parse-time arguments for each. Used by the AML
* parser Each list is compressed into a 32-bit number and stored in the
* master opcode table (in psopcode.c).
*/
@@ -193,7 +193,7 @@
#define ARGP_ZERO_OP ARG_NONE
/*
- * All AML opcodes and the runtime arguments for each. Used by the AML
+ * All AML opcodes and the runtime arguments for each. Used by the AML
* interpreter Each list is compressed into a 32-bit number and stored
* in the master opcode table (in psopcode.c).
*
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index b725d780d34d..eefcf47a61a0 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -150,8 +150,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state);
void
acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
- union acpi_parse_object **op,
- u32 * arg_list, u32 * arg_count);
+ union acpi_parse_object **op, u32 *arg_list, u32 *arg_count);
acpi_status
acpi_ps_push_scope(struct acpi_parse_state *parser_state,
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h
index 3080c017f5ba..9dfa1c83bd4e 100644
--- a/drivers/acpi/acpica/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
@@ -150,8 +150,7 @@ enum acpi_return_package_types {
* is saved here (rather than in a separate table) in order to minimize the
* overall size of the stored data.
*/
-static const union acpi_predefined_info predefined_names[] =
-{
+static const union acpi_predefined_info predefined_names[] = {
{{"_AC0", 0, ACPI_RTYPE_INTEGER}},
{{"_AC1", 0, ACPI_RTYPE_INTEGER}},
{{"_AC2", 0, ACPI_RTYPE_INTEGER}},
@@ -538,7 +537,8 @@ static const union acpi_predefined_info predefined_names[] =
/* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
- {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
+ {{"_WAK", 1,
+ ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
{{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */
/* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */
@@ -551,11 +551,12 @@ static const union acpi_predefined_info predefined_names[] =
};
#if 0
+
/* This is an internally implemented control method, no need to check */
- {{"_OSI", 1, ACPI_RTYPE_INTEGER}},
+{ {
+"_OSI", 1, ACPI_RTYPE_INTEGER}},
/* TBD: */
-
_PRT - currently ignore reversed entries. attempt to fix here?
think about possibly fixing package elements like _BIF, etc.
#endif
diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h
index f196e2c9a71f..937e66c65d1e 100644
--- a/drivers/acpi/acpica/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
@@ -53,7 +53,7 @@
****************************************************************************/
/*
- * Walk state - current state of a parse tree walk. Used for both a leisurely
+ * Walk state - current state of a parse tree walk. Used for both a leisurely
* stroll through the tree (for whatever reason), and for control method
* execution.
*/
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 5035327ebccc..b0f5f92b674a 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -69,6 +69,22 @@ extern const char *acpi_gbl_siz_decode[];
extern const char *acpi_gbl_trs_decode[];
extern const char *acpi_gbl_ttp_decode[];
extern const char *acpi_gbl_typ_decode[];
+extern const char *acpi_gbl_ppc_decode[];
+extern const char *acpi_gbl_ior_decode[];
+extern const char *acpi_gbl_dts_decode[];
+extern const char *acpi_gbl_ct_decode[];
+extern const char *acpi_gbl_sbt_decode[];
+extern const char *acpi_gbl_am_decode[];
+extern const char *acpi_gbl_sm_decode[];
+extern const char *acpi_gbl_wm_decode[];
+extern const char *acpi_gbl_cph_decode[];
+extern const char *acpi_gbl_cpo_decode[];
+extern const char *acpi_gbl_dp_decode[];
+extern const char *acpi_gbl_ed_decode[];
+extern const char *acpi_gbl_bpb_decode[];
+extern const char *acpi_gbl_sb_decode[];
+extern const char *acpi_gbl_fc_decode[];
+extern const char *acpi_gbl_pt_decode[];
#endif
/* Types for Resource descriptor entries */
@@ -79,14 +95,14 @@ extern const char *acpi_gbl_typ_decode[];
#define ACPI_SMALL_VARIABLE_LENGTH 3
typedef
-acpi_status(*acpi_walk_aml_callback) (u8 * aml,
+acpi_status(*acpi_walk_aml_callback) (u8 *aml,
u32 length,
u32 offset,
u8 resource_index, void **context);
typedef
acpi_status(*acpi_pkg_callback) (u8 object_type,
- union acpi_operand_object * source_object,
+ union acpi_operand_object *source_object,
union acpi_generic_state * state,
void *context);
@@ -202,7 +218,9 @@ extern const u8 _acpi_ctype[];
#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
-#endif /* ACPI_USE_SYSTEM_CLIBRARY */
+#endif /* !ACPI_USE_SYSTEM_CLIBRARY */
+
+#define ACPI_IS_ASCII(c) ((c) < 0x80)
/*
* utcopy - Object construction and conversion interfaces
@@ -210,11 +228,11 @@ extern const u8 _acpi_ctype[];
acpi_status
acpi_ut_build_simple_object(union acpi_operand_object *obj,
union acpi_object *user_obj,
- u8 * data_space, u32 * buffer_space_used);
+ u8 *data_space, u32 *buffer_space_used);
acpi_status
acpi_ut_build_package_object(union acpi_operand_object *obj,
- u8 * buffer, u32 * space_used);
+ u8 *buffer, u32 *space_used);
acpi_status
acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj,
@@ -287,9 +305,10 @@ acpi_ut_ptr_exit(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, u8 *ptr);
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id);
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display);
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
void acpi_ut_report_error(char *module_name, u32 line_number);
@@ -337,15 +356,19 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
*/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
- struct acpica_device_id **return_id);
+ struct acpi_pnp_device_id ** return_id);
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
- struct acpica_device_id **return_id);
+ struct acpi_pnp_device_id ** return_id);
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+ struct acpi_pnp_device_id **return_id);
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
- struct acpica_device_id_list **return_cid_list);
+ struct acpi_pnp_device_id_list ** return_cid_list);
/*
* utlock - reader/writer locks
@@ -479,15 +502,19 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
void acpi_ut_strupr(char *src_string);
+void acpi_ut_strlwr(char *src_string);
+
+int acpi_ut_stricmp(char *string1, char *string2);
+
void acpi_ut_print_string(char *string, u8 max_length);
u8 acpi_ut_valid_acpi_name(u32 name);
-acpi_name acpi_ut_repair_name(char *name);
+void acpi_ut_repair_name(char *name);
u8 acpi_ut_valid_acpi_char(char character, u32 position);
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
/* Values for Base above (16=Hex, 10=Decimal) */
@@ -508,12 +535,12 @@ acpi_ut_display_init_pathname(u8 type,
* utresrc
*/
acpi_status
-acpi_ut_walk_aml_resources(u8 * aml,
+acpi_ut_walk_aml_resources(u8 *aml,
acpi_size aml_length,
acpi_walk_aml_callback user_function,
void **context);
-acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
+acpi_status acpi_ut_validate_resource(void *aml, u8 *return_index);
u32 acpi_ut_get_descriptor_length(void *aml);
@@ -524,8 +551,7 @@ u8 acpi_ut_get_resource_header_length(void *aml);
u8 acpi_ut_get_resource_type(void *aml);
acpi_status
-acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
- u8 ** end_tag);
+acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag);
/*
* utmutex - mutex support
diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index af4947956ec2..968449685e06 100644
--- a/drivers/acpi/acpica/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: amlresrc.h - AML resource descriptors
diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c
index 465f02134b89..57895db3231a 100644
--- a/drivers/acpi/acpica/dscontrol.c
+++ b/drivers/acpi/acpica/dscontrol.c
@@ -280,7 +280,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
/*
* Get the return value and save as the last result
- * value. This is the only place where walk_state->return_desc
+ * value. This is the only place where walk_state->return_desc
* is set to anything other than zero!
*/
walk_state->return_desc = walk_state->operands[0];
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 3da6fd8530c5..b5b904ee815f 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -277,7 +277,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
*
* RETURN: Status
*
- * DESCRIPTION: Process all named fields in a field declaration. Names are
+ * DESCRIPTION: Process all named fields in a field declaration. Names are
* entered into the namespace.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index aa9a5d4e4052..52eb4e01622a 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -170,7 +170,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)
*
* RETURN: Status
*
- * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
+ * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
* increments the thread count, and waits at the method semaphore
* for clearance to execute.
*
@@ -444,7 +444,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
* RETURN: Status
*
* DESCRIPTION: Restart a method that was preempted by another (nested) method
- * invocation. Handle the return value (if any) from the callee.
+ * invocation. Handle the return value (if any) from the callee.
*
******************************************************************************/
@@ -530,7 +530,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
*
* RETURN: None
*
- * DESCRIPTION: Terminate a control method. Delete everything that the method
+ * DESCRIPTION: Terminate a control method. Delete everything that the method
* created, delete all locals and arguments, and delete the parse
* tree if requested.
*
diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index 8d55cebaa656..9a83b7e0f3ba 100644
--- a/drivers/acpi/acpica/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -76,7 +76,7 @@ acpi_ds_method_data_get_type(u16 opcode,
* RETURN: Status
*
* DESCRIPTION: Initialize the data structures that hold the method's arguments
- * and locals. The data struct is an array of namespace nodes for
+ * and locals. The data struct is an array of namespace nodes for
* each - this allows ref_of and de_ref_of to work properly for these
* special data types.
*
@@ -129,7 +129,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
*
* RETURN: None
*
- * DESCRIPTION: Delete method locals and arguments. Arguments are only
+ * DESCRIPTION: Delete method locals and arguments. Arguments are only
* deleted if this method was called from another method.
*
******************************************************************************/
@@ -183,7 +183,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
*
* RETURN: Status
*
- * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
+ * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
* of ACPI operand objects, either null terminated or whose length
* is defined by max_param_count.
*
@@ -401,7 +401,7 @@ acpi_ds_method_data_get_value(u8 type,
* This means that either 1) The expected argument was
* not passed to the method, or 2) A local variable
* was referenced by the method (via the ASL)
- * before it was initialized. Either case is an error.
+ * before it was initialized. Either case is an error.
*/
/* If slack enabled, init the local_x/arg_x to an Integer of value zero */
@@ -465,7 +465,7 @@ acpi_ds_method_data_get_value(u8 type,
*
* RETURN: None
*
- * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
+ * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
* a null into the stack slot after the object is deleted.
*
******************************************************************************/
@@ -523,7 +523,7 @@ acpi_ds_method_data_delete_value(u8 type,
*
* RETURN: Status
*
- * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
+ * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
* as the new value for the Arg or Local and the reference count
* for obj_desc is incremented.
*
@@ -566,7 +566,7 @@ acpi_ds_store_object_to_local(u8 type,
/*
* If the reference count on the object is more than one, we must
- * take a copy of the object before we store. A reference count
+ * take a copy of the object before we store. A reference count
* of exactly 1 means that the object was just created during the
* evaluation of an expression, and we can safely use it since it
* is not used anywhere else.
diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c
index 68592dd34960..c9f15d3a3686 100644
--- a/drivers/acpi/acpica/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -293,7 +293,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
/*
* Second arg is the buffer data (optional) byte_list can be either
- * individual bytes or a string initializer. In either case, a
+ * individual bytes or a string initializer. In either case, a
* byte_list appears in the AML.
*/
arg = op->common.value.arg; /* skip first arg */
@@ -568,7 +568,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
/*
* Because of the execution pass through the non-control-method
- * parts of the table, we can arrive here twice. Only init
+ * parts of the table, we can arrive here twice. Only init
* the named object node the first time through
*/
if (acpi_ns_get_attached_object(node)) {
@@ -618,7 +618,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
* RETURN: Status
*
* DESCRIPTION: Initialize a namespace object from a parser Op and its
- * associated arguments. The namespace object is a more compact
+ * associated arguments. The namespace object is a more compact
* representation of the Op and its arguments.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index aa34d8984d34..0df024e5fb63 100644
--- a/drivers/acpi/acpica/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -649,7 +649,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
(op->common.parent->common.aml_opcode !=
AML_VAR_PACKAGE_OP)
- && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+ && (op->common.parent->common.aml_opcode !=
+ AML_NAME_OP))) {
walk_state->result_obj = obj_desc;
}
}
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
index 73a5447475f5..afeb99f49482 100644
--- a/drivers/acpi/acpica/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("dsutils")
*
* RETURN: None.
*
- * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
* to delete "stale" return values (if enabled, the return value
* from every operator is saved at least momentarily, in case the
* parent method exits.)
@@ -107,7 +107,7 @@ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
*
* DESCRIPTION: Implements the optional "implicit return". We save the result
* of every ASL operator and control method invocation in case the
- * parent method exit. Before storing a new return value, we
+ * parent method exit. Before storing a new return value, we
* delete the previous return value.
*
******************************************************************************/
@@ -198,7 +198,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
*
* If there is no parent, or the parent is a scope_op, we are executing
* at the method level. An executing method typically has no parent,
- * since each method is parsed separately. A method invoked externally
+ * since each method is parsed separately. A method invoked externally
* via execute_control_method has a scope_op as the parent.
*/
if ((!op->common.parent) ||
@@ -223,7 +223,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
}
/*
- * Decide what to do with the result based on the parent. If
+ * Decide what to do with the result based on the parent. If
* the parent opcode will not use the result, delete the object.
* Otherwise leave it as is, it will be deleted when it is used
* as an operand later.
@@ -266,7 +266,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
/*
* These opcodes allow term_arg(s) as operands and therefore
- * the operands can be method calls. The result is used.
+ * the operands can be method calls. The result is used.
*/
goto result_used;
@@ -284,7 +284,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
AML_BANK_FIELD_OP)) {
/*
* These opcodes allow term_arg(s) as operands and therefore
- * the operands can be method calls. The result is used.
+ * the operands can be method calls. The result is used.
*/
goto result_used;
}
@@ -329,9 +329,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
*
* RETURN: Status
*
- * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
+ * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
* result descriptor, check if the parent opcode will actually use
- * this result. If not, delete the result now so that it will
+ * this result. If not, delete the result now so that it will
* not become orphaned.
*
******************************************************************************/
@@ -376,7 +376,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
*
* RETURN: Status
*
- * DESCRIPTION: Resolve all operands to their values. Used to prepare
+ * DESCRIPTION: Resolve all operands to their values. Used to prepare
* arguments to a control method invocation (a call from one
* method to another.)
*
@@ -391,7 +391,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
/*
* Attempt to resolve each of the valid operands
- * Method arguments are passed by reference, not by value. This means
+ * Method arguments are passed by reference, not by value. This means
* that the actual objects are passed, not copies of the objects.
*/
for (i = 0; i < walk_state->num_operands; i++) {
@@ -451,7 +451,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
* RETURN: Status
*
* DESCRIPTION: Translate a parse tree object that is an argument to an AML
- * opcode to the equivalent interpreter object. This may include
+ * opcode to the equivalent interpreter object. This may include
* looking up a name or entering a new name into the internal
* namespace.
*
@@ -496,9 +496,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
/*
* Special handling for buffer_field declarations. This is a deferred
* opcode that unfortunately defines the field name as the last
- * parameter instead of the first. We get here when we are performing
+ * parameter instead of the first. We get here when we are performing
* the deferred execution, so the actual name of the field is already
- * in the namespace. We don't want to attempt to look it up again
+ * in the namespace. We don't want to attempt to look it up again
* because we may be executing in a different scope than where the
* actual opcode exists.
*/
@@ -560,7 +560,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
* indicate this to the interpreter, set the
* object to the root
*/
- obj_desc = ACPI_CAST_PTR(union
+ obj_desc =
+ ACPI_CAST_PTR(union
acpi_operand_object,
acpi_gbl_root_node);
status = AE_OK;
@@ -604,8 +605,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
/*
* If the name is null, this means that this is an
* optional result parameter that was not specified
- * in the original ASL. Create a Zero Constant for a
- * placeholder. (Store to a constant is a Noop.)
+ * in the original ASL. Create a Zero Constant for a
+ * placeholder. (Store to a constant is a Noop.)
*/
opcode = AML_ZERO_OP; /* Has no arguments! */
diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c
index 642f3c053e87..58593931be96 100644
--- a/drivers/acpi/acpica/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -57,7 +57,7 @@ ACPI_MODULE_NAME("dswexec")
/*
* Dispatch table for opcode classes
*/
-static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = {
+static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
acpi_ex_opcode_0A_0T_1R,
acpi_ex_opcode_1A_0T_0R,
acpi_ex_opcode_1A_0T_1R,
@@ -204,7 +204,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
* RETURN: Status
*
* DESCRIPTION: Descending callback used during the execution of control
- * methods. This is where most operators and operands are
+ * methods. This is where most operators and operands are
* dispatched to the interpreter.
*
****************************************************************************/
@@ -297,7 +297,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
if (walk_state->walk_type & ACPI_WALK_METHOD) {
/*
* Found a named object declaration during method execution;
- * we must enter this object into the namespace. The created
+ * we must enter this object into the namespace. The created
* object is temporary and will be deleted upon completion of
* the execution of this method.
*
@@ -348,7 +348,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
* RETURN: Status
*
* DESCRIPTION: Ascending callback used during the execution of control
- * methods. The only thing we really need to do here is to
+ * methods. The only thing we really need to do here is to
* notice the beginning of IF, ELSE, and WHILE blocks.
*
****************************************************************************/
@@ -432,7 +432,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
if (ACPI_SUCCESS(status)) {
/*
* Dispatch the request to the appropriate interpreter handler
- * routine. There is one routine per opcode "type" based upon the
+ * routine. There is one routine per opcode "type" based upon the
* number of opcode arguments and return type.
*/
status =
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index 89c0114210c0..379835748357 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -254,7 +254,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
acpi_ut_get_type_name(node->type),
acpi_ut_get_node_name(node)));
- return (AE_AML_OPERAND_TYPE);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
@@ -602,7 +602,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
region_space,
walk_state);
if (ACPI_FAILURE(status)) {
- return (status);
+ return_ACPI_STATUS(status);
}
acpi_ex_exit_interpreter();
diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
index d0e6555061e4..3e65a15a735f 100644
--- a/drivers/acpi/acpica/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -51,8 +51,9 @@
ACPI_MODULE_NAME("dswstate")
/* Local prototypes */
-static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws);
-static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws);
+static acpi_status
+acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
+static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
/*******************************************************************************
*
@@ -347,7 +348,7 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
*
* RETURN: Status
*
- * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
+ * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
* deleted by this routine.
*
******************************************************************************/
@@ -491,7 +492,7 @@ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
* RETURN: A walk_state object popped from the thread's stack
*
* DESCRIPTION: Remove and return the walkstate object that is at the head of
- * the walk stack for the given walk list. NULL indicates that
+ * the walk stack for the given walk list. NULL indicates that
* the list is empty.
*
******************************************************************************/
@@ -531,14 +532,17 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
*
* RETURN: Pointer to the new walk state.
*
- * DESCRIPTION: Allocate and initialize a new walk state. The current walk
+ * DESCRIPTION: Allocate and initialize a new walk state. The current walk
* state is set to this new state.
*
******************************************************************************/
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
- *origin, union acpi_operand_object
- *method_desc, struct acpi_thread_state
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
+ union acpi_parse_object
+ *origin,
+ union acpi_operand_object
+ *method_desc,
+ struct acpi_thread_state
*thread)
{
struct acpi_walk_state *walk_state;
@@ -653,7 +657,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
/*
* Setup the current scope.
* Find a Named Op that has a namespace node associated with it.
- * search upwards from this Op. Current scope is the first
+ * search upwards from this Op. Current scope is the first
* Op with a namespace node.
*/
extra_op = parser_state->start_op;
@@ -704,13 +708,13 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
if (!walk_state) {
- return;
+ return_VOID;
}
if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
walk_state));
- return;
+ return_VOID;
}
/* There should not be any open scopes */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index ef0193d74b5d..36d120574423 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -89,7 +89,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
/* Set the mask bit only if there are references to this GPE */
if (gpe_event_info->runtime_count) {
- ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit);
+ ACPI_SET_BIT(gpe_register_info->enable_for_run,
+ (u8)register_bit);
}
return_ACPI_STATUS(AE_OK);
@@ -106,8 +107,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
* DESCRIPTION: Clear a GPE of stale events and enable it.
*
******************************************************************************/
-acpi_status
-acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
@@ -131,8 +131,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
}
/* Enable the requested GPE */
- status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
return_ACPI_STATUS(status);
}
@@ -150,7 +150,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
*
******************************************************************************/
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status = AE_OK;
@@ -191,7 +192,8 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info
*
******************************************************************************/
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status = AE_OK;
@@ -208,7 +210,8 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i
status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
if (ACPI_SUCCESS(status)) {
- status = acpi_hw_low_set_gpe(gpe_event_info,
+ status =
+ acpi_hw_low_set_gpe(gpe_event_info,
ACPI_GPE_DISABLE);
}
@@ -306,7 +309,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
/* A Non-NULL gpe_device means this is a GPE Block Device */
- obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
+ obj_desc =
+ acpi_ns_get_attached_object((struct acpi_namespace_node *)
gpe_device);
if (!obj_desc || !obj_desc->device.gpe_block) {
return (NULL);
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 8cf4c104c7b7..1571a61a7833 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -486,7 +486,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not enable GPE 0x%02X",
- gpe_index + gpe_block->block_base_number));
+ gpe_index +
+ gpe_block->block_base_number));
continue;
}
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index cb50dd91bc18..228a0c3b1d49 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -374,7 +374,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
gpe_event_info->dispatch.handler = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
- } else if ((gpe_event_info->
+ } else
+ if ((gpe_event_info->
flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_NOTIFY) {
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 4c1c8261166f..1474241bfc7e 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -227,8 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
/* Install a handler for this PCI root bridge */
- status =
- acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+ status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
if (ACPI_FAILURE(status)) {
if (status == AE_SAME_HANDLER) {
/*
@@ -350,8 +349,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
{
acpi_status status;
- struct acpica_device_id *hid;
- struct acpica_device_id_list *cid;
+ struct acpi_pnp_device_id *hid;
+ struct acpi_pnp_device_id_list *cid;
u32 i;
u8 match;
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 7587eb6c9584..ae668f32cf16 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -398,7 +398,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
*
******************************************************************************/
acpi_status
-acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
+acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
{
acpi_status status;
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 87c5f2332260..3f30e753b652 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -221,7 +221,8 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
if (wake_device == ACPI_ROOT_OBJECT) {
device_node = acpi_gbl_root_node;
} else {
- device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
+ device_node =
+ ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
}
/* Validate WakeDevice is of type Device */
@@ -324,7 +325,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
*
******************************************************************************/
-acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
+acpi_status
+acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
@@ -567,7 +569,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
- return (status);
+ return_ACPI_STATUS(status);
}
node = acpi_ns_validate_handle(gpe_device);
@@ -650,7 +652,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
- return (status);
+ return_ACPI_STATUS(status);
}
node = acpi_ns_validate_handle(gpe_device);
@@ -694,8 +696,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
* the FADT-defined gpe blocks. Otherwise, the GPE block device.
*
******************************************************************************/
-acpi_status
-acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
+acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
{
struct acpi_gpe_device_info info;
acpi_status status;
diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index bfb062e4c4b4..4492a4e03022 100644
--- a/drivers/acpi/acpica/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -516,8 +516,8 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
string_length--;
}
- return_desc = acpi_ut_create_string_object((acpi_size)
- string_length);
+ return_desc =
+ acpi_ut_create_string_object((acpi_size) string_length);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 691d4763102c..66554bc6f9a8 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -78,7 +78,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
(target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
/*
* Dereference an existing alias so that we don't create a chain
- * of aliases. With this code, we guarantee that an alias is
+ * of aliases. With this code, we guarantee that an alias is
* always exactly one level of indirection away from the
* actual aliased name.
*/
@@ -90,7 +90,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
/*
* For objects that can never change (i.e., the NS node will
* permanently point to the same object), we can simply attach
- * the object to the new NS node. For other objects (such as
+ * the object to the new NS node. For other objects (such as
* Integers, buffers, etc.), we have to point the Alias node
* to the original Node.
*/
@@ -139,7 +139,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
/*
* The new alias assumes the type of the target, and it points
- * to the same object. The reference count of the object has an
+ * to the same object. The reference count of the object has an
* additional reference to prevent deletion out from under either the
* target node or the alias Node
*/
@@ -243,8 +243,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
/* Init object and attach to NS node */
- obj_desc->mutex.sync_level =
- (u8) walk_state->operands[1]->integer.value;
+ obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
obj_desc->mutex.node =
(struct acpi_namespace_node *)walk_state->operands[0];
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
index bc5b9a6a1316..d7c9f51608a7 100644
--- a/drivers/acpi/acpica/exdebug.c
+++ b/drivers/acpi/acpica/exdebug.c
@@ -145,10 +145,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
case ACPI_TYPE_BUFFER:
acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length);
- acpi_ut_dump_buffer2(source_desc->buffer.pointer,
- (source_desc->buffer.length < 256) ?
- source_desc->buffer.length : 256,
- DB_BYTE_DISPLAY);
+ acpi_ut_dump_buffer(source_desc->buffer.pointer,
+ (source_desc->buffer.length < 256) ?
+ source_desc->buffer.length : 256,
+ DB_BYTE_DISPLAY, 0);
break;
case ACPI_TYPE_STRING:
@@ -190,7 +190,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
acpi_os_printf("Table Index 0x%X\n",
source_desc->reference.value);
- return;
+ return_VOID;
default:
break;
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c
index 213c081776fc..858b43a7dcf6 100644
--- a/drivers/acpi/acpica/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -464,7 +464,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
ACPI_FUNCTION_NAME(ex_dump_operand)
- if (!((ACPI_LV_EXEC & acpi_dbg_level)
+ if (!
+ ((ACPI_LV_EXEC & acpi_dbg_level)
&& (_COMPONENT & acpi_dbg_layer))) {
return;
}
@@ -777,7 +778,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
* PARAMETERS: title - Descriptive text
* value - Value to be displayed
*
- * DESCRIPTION: Object dump output formatting functions. These functions
+ * DESCRIPTION: Object dump output formatting functions. These functions
* reduce the number of format strings required and keeps them
* all in one place for easy modification.
*
@@ -810,7 +811,8 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
ACPI_FUNCTION_ENTRY();
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
&& (_COMPONENT & acpi_dbg_layer))) {
return;
}
@@ -940,10 +942,11 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
acpi_os_printf("[Buffer] Length %.2X = ",
obj_desc->buffer.length);
if (obj_desc->buffer.length) {
- acpi_ut_dump_buffer(ACPI_CAST_PTR
- (u8, obj_desc->buffer.pointer),
- obj_desc->buffer.length,
- DB_DWORD_DISPLAY, _COMPONENT);
+ acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
+ (u8,
+ obj_desc->buffer.pointer),
+ obj_desc->buffer.length,
+ DB_DWORD_DISPLAY, _COMPONENT);
} else {
acpi_os_printf("\n");
}
@@ -996,7 +999,8 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
}
if (!flags) {
- if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+ if (!
+ ((ACPI_LV_OBJECTS & acpi_dbg_level)
&& (_COMPONENT & acpi_dbg_layer))) {
return_VOID;
}
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index dc092f5b35d6..ebc55fbf3ff7 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -59,7 +59,7 @@ ACPI_MODULE_NAME("exfield")
*
* RETURN: Status
*
- * DESCRIPTION: Read from a named field. Returns either an Integer or a
+ * DESCRIPTION: Read from a named field. Returns either an Integer or a
* Buffer, depending on the size of the field.
*
******************************************************************************/
@@ -149,7 +149,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
* Allocate a buffer for the contents of the field.
*
* If the field is larger than the current integer width, create
- * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
+ * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
* the use of arithmetic operators on the returned value if the
* field size is equal or smaller than an Integer.
*
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index a7784152ed30..aa2ccfb7cb61 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -54,8 +54,7 @@ ACPI_MODULE_NAME("exfldio")
/* Local prototypes */
static acpi_status
acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
- u32 field_datum_byte_offset,
- u64 *value, u32 read_write);
+ u32 field_datum_byte_offset, u64 *value, u32 read_write);
static u8
acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
@@ -155,7 +154,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
#endif
/*
- * Validate the request. The entire request from the byte offset for a
+ * Validate the request. The entire request from the byte offset for a
* length of one field datum (access width) must fit within the region.
* (Region length is specified in bytes)
*/
@@ -183,7 +182,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
obj_desc->common_field.access_byte_width) {
/*
* This is the case where the access_type (acc_word, etc.) is wider
- * than the region itself. For example, a region of length one
+ * than the region itself. For example, a region of length one
* byte, and a field with Dword access specified.
*/
ACPI_ERROR((AE_INFO,
@@ -321,7 +320,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
*
* DESCRIPTION: Check if a value is out of range of the field being written.
* Used to check if the values written to Index and Bank registers
- * are out of range. Normally, the value is simply truncated
+ * are out of range. Normally, the value is simply truncated
* to fit the field, but this case is most likely a serious
* coding error in the ASL.
*
@@ -370,7 +369,7 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
*
* RETURN: Status
*
- * DESCRIPTION: Read or Write a single datum of a field. The field_type is
+ * DESCRIPTION: Read or Write a single datum of a field. The field_type is
* demultiplexed here to handle the different types of fields
* (buffer_field, region_field, index_field, bank_field)
*
@@ -860,7 +859,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
/*
* We must have a buffer that is at least as long as the field
- * we are writing to. This is because individual fields are
+ * we are writing to. This is because individual fields are
* indivisible and partial writes are not supported -- as per
* the ACPI specification.
*/
@@ -875,7 +874,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
/*
* Copy the original data to the new buffer, starting
- * at Byte zero. All unused (upper) bytes of the
+ * at Byte zero. All unused (upper) bytes of the
* buffer will be 0.
*/
ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c
index 271c0c57ea10..84058705ed12 100644
--- a/drivers/acpi/acpica/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
@@ -254,7 +253,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
ACPI_FUNCTION_TRACE(ex_do_concatenate);
/*
- * Convert the second operand if necessary. The first operand
+ * Convert the second operand if necessary. The first operand
* determines the type of the second operand, (See the Data Types
* section of the ACPI specification.) Both object types are
* guaranteed to be either Integer/String/Buffer by the operand
@@ -573,7 +572,7 @@ acpi_ex_do_logical_op(u16 opcode,
ACPI_FUNCTION_TRACE(ex_do_logical_op);
/*
- * Convert the second operand if necessary. The first operand
+ * Convert the second operand if necessary. The first operand
* determines the type of the second operand, (See the Data Types
* section of the ACPI 3.0+ specification.) Both object types are
* guaranteed to be either Integer/String/Buffer by the operand
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index bcceda5be9e3..d1f449d93dcf 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exmutex - ASL Mutex Acquire/Release functions
@@ -305,7 +304,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
ACPI_FUNCTION_TRACE(ex_release_mutex_object);
if (obj_desc->mutex.acquisition_depth == 0) {
- return (AE_NOT_ACQUIRED);
+ return_ACPI_STATUS(AE_NOT_ACQUIRED);
}
/* Match multiple Acquires with multiple Releases */
@@ -462,7 +461,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
union acpi_operand_object *next = thread->acquired_mutex_list;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_ENTRY();
+ ACPI_FUNCTION_NAME(ex_release_all_mutexes);
/* Traverse the list of owned mutexes, releasing each one */
@@ -474,6 +473,10 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
obj_desc->mutex.next = NULL;
obj_desc->mutex.acquisition_depth = 0;
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Force-releasing held mutex: %p\n",
+ obj_desc));
+
/* Release the mutex, special case for Global Lock */
if (obj_desc == acpi_gbl_global_lock_mutex) {
diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c
index fcc75fa27d32..2ff578a16adc 100644
--- a/drivers/acpi/acpica/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exnames - interpreter/scanner name load/execute
@@ -53,8 +52,7 @@ ACPI_MODULE_NAME("exnames")
/* Local prototypes */
static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
-static acpi_status
-acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
+static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
/*******************************************************************************
*
@@ -64,7 +62,7 @@ acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
* (-1)==root, 0==none
* num_name_segs - count of 4-character name segments
*
- * RETURN: A pointer to the allocated string segment. This segment must
+ * RETURN: A pointer to the allocated string segment. This segment must
* be deleted by the caller.
*
* DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
@@ -178,7 +176,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
- for (index = 0; (index < ACPI_NAME_SIZE)
+ for (index = 0;
+ (index < ACPI_NAME_SIZE)
&& (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
char_buf[index] = *aml_address++;
ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index 9ba8c73cea16..bbf01e9bf057 100644
--- a/drivers/acpi/acpica/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exoparg1 - AML execution - opcodes with 1 argument
@@ -606,7 +605,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
}
/*
- * Set result to ONES (TRUE) if Value == 0. Note:
+ * Set result to ONES (TRUE) if Value == 0. Note:
* return_desc->Integer.Value is initially == 0 (FALSE) from above.
*/
if (!operand[0]->integer.value) {
@@ -618,7 +617,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
case AML_INCREMENT_OP: /* Increment (Operand) */
/*
- * Create a new integer. Can't just get the base integer and
+ * Create a new integer. Can't just get the base integer and
* increment it because it may be an Arg or Field.
*/
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -686,7 +685,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
/*
* Note: The operand is not resolved at this point because we want to
- * get the associated object, not its value. For example, we don't
+ * get the associated object, not its value. For example, we don't
* want to resolve a field_unit to its value, we want the actual
* field_unit object.
*/
@@ -727,7 +726,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
/*
* The type of the base object must be integer, buffer, string, or
- * package. All others are not supported.
+ * package. All others are not supported.
*
* NOTE: Integer is not specifically supported by the ACPI spec,
* but is supported implicitly via implicit operand conversion.
@@ -965,7 +964,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
case ACPI_TYPE_PACKAGE:
/*
- * Return the referenced element of the package. We must
+ * Return the referenced element of the package. We must
* add another reference to the referenced object, however.
*/
return_desc =
diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index 879e8a277b94..ee5634a074c4 100644
--- a/drivers/acpi/acpica/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -123,7 +123,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
/*
* Dispatch the notify to the appropriate handler
* NOTE: the request is queued for execution after this method
- * completes. The notify handlers are NOT invoked synchronously
+ * completes. The notify handlers are NOT invoked synchronously
* from this thread -- because handlers may in turn run other
* control methods.
*/
diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index 71fcc65c9ffa..2c89b4651f08 100644
--- a/drivers/acpi/acpica/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exoparg3 - AML execution - opcodes with 3 arguments
@@ -158,7 +157,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
/*
- * Create the return object. The Source operand is guaranteed to be
+ * Create the return object. The Source operand is guaranteed to be
* either a String or a Buffer, so just use its type.
*/
return_desc = acpi_ut_create_internal_object((operand[0])->
diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index 0786b8659061..3e08695c3b30 100644
--- a/drivers/acpi/acpica/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exoparg6 - AML execution - opcodes with 6 arguments
@@ -198,7 +197,7 @@ acpi_ex_do_match(u32 match_op,
return (FALSE);
}
- return logical_result;
+ return (logical_result);
}
/*******************************************************************************
@@ -269,7 +268,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
* and the next should be examined.
*
* Upon finding a match, the loop will terminate via "break" at
- * the bottom. If it terminates "normally", match_value will be
+ * the bottom. If it terminates "normally", match_value will be
* ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 81eca60d2748..ba9db4de7c89 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
@@ -78,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset,
* any_acc keyword.
*
* NOTE: Need to have the region_length in order to check for boundary
- * conditions (end-of-region). However, the region_length is a deferred
- * operation. Therefore, to complete this implementation, the generation
+ * conditions (end-of-region). However, the region_length is a deferred
+ * operation. Therefore, to complete this implementation, the generation
* of this access width must be deferred until the region length has
* been evaluated.
*
@@ -308,7 +307,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
* RETURN: Status
*
* DESCRIPTION: Initialize the areas of the field object that are common
- * to the various types of fields. Note: This is very "sensitive"
+ * to the various types of fields. Note: This is very "sensitive"
* code because we are solving the general case for field
* alignment.
*
@@ -336,13 +335,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
obj_desc->common_field.bit_length = field_bit_length;
/*
- * Decode the access type so we can compute offsets. The access type gives
+ * Decode the access type so we can compute offsets. The access type gives
* two pieces of information - the width of each field access and the
* necessary byte_alignment (address granularity) of the access.
*
* For any_acc, the access_bit_width is the largest width that is both
* necessary and possible in an attempt to access the whole field in one
- * I/O operation. However, for any_acc, the byte_alignment is always one
+ * I/O operation. However, for any_acc, the byte_alignment is always one
* byte.
*
* For all Buffer Fields, the byte_alignment is always one byte.
@@ -363,7 +362,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
/*
* base_byte_offset is the address of the start of the field within the
- * region. It is the byte address of the first *datum* (field-width data
+ * region. It is the byte address of the first *datum* (field-width data
* unit) of the field. (i.e., the first datum that contains at least the
* first *bit* of the field.)
*
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c
index 1f1ce0c3d2f8..1db2c0bfde0b 100644
--- a/drivers/acpi/acpica/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exregion - ACPI default op_region (address space) handlers
@@ -202,7 +201,7 @@ acpi_ex_system_memory_space_handler(u32 function,
* Perform the memory read or write
*
* Note: For machines that do not support non-aligned transfers, the target
- * address was checked for alignment above. We do not attempt to break the
+ * address was checked for alignment above. We do not attempt to break the
* transfer up into smaller (byte-size) chunks because the AML specifically
* asked for a transfer width that the hardware may require.
*/
diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c
index fa50e77e64a8..6239956786eb 100644
--- a/drivers/acpi/acpica/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exresnte - AML Interpreter object resolution
@@ -58,8 +57,8 @@ ACPI_MODULE_NAME("exresnte")
* PARAMETERS: object_ptr - Pointer to a location that contains
* a pointer to a NS node, and will receive a
* pointer to the resolved object.
- * walk_state - Current state. Valid only if executing AML
- * code. NULL if simply resolving an object
+ * walk_state - Current state. Valid only if executing AML
+ * code. NULL if simply resolving an object
*
* RETURN: Status
*
@@ -67,7 +66,7 @@ ACPI_MODULE_NAME("exresnte")
*
* Note: for some of the data types, the pointer attached to the Node
* can be either a pointer to an actual internal object or a pointer into the
- * AML stream itself. These types are currently:
+ * AML stream itself. These types are currently:
*
* ACPI_TYPE_INTEGER
* ACPI_TYPE_STRING
@@ -89,7 +88,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
/*
- * The stack pointer points to a struct acpi_namespace_node (Node). Get the
+ * The stack pointer points to a struct acpi_namespace_node (Node). Get the
* object that is attached to the Node.
*/
node = *object_ptr;
diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c
index bbf40ac27585..cc176b245e22 100644
--- a/drivers/acpi/acpica/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exresolv - AML Interpreter object resolution
@@ -327,7 +326,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
*
* RETURN: Status
*
- * DESCRIPTION: Return the base object and type. Traverse a reference list if
+ * DESCRIPTION: Return the base object and type. Traverse a reference list if
* necessary to get to the base object.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c
index f232fbabdea8..b9ebff2f6a09 100644
--- a/drivers/acpi/acpica/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exresop - AML Interpreter operand/object resolution
@@ -87,7 +86,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
/*
* Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
- * objects and thus allow them to be targets. (As per the ACPI
+ * objects and thus allow them to be targets. (As per the ACPI
* specification, a store to a constant is a noop.)
*/
if ((this_type == ACPI_TYPE_INTEGER) &&
@@ -337,7 +336,8 @@ acpi_ex_resolve_operands(u16 opcode,
if ((opcode == AML_STORE_OP) &&
((*stack_ptr)->common.type ==
ACPI_TYPE_LOCAL_REFERENCE)
- && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) {
+ && ((*stack_ptr)->reference.class ==
+ ACPI_REFCLASS_INDEX)) {
goto next_operand;
}
break;
@@ -638,7 +638,7 @@ acpi_ex_resolve_operands(u16 opcode,
if (acpi_gbl_enable_interpreter_slack) {
/*
* Enable original behavior of Store(), allowing any and all
- * objects as the source operand. The ACPI spec does not
+ * objects as the source operand. The ACPI spec does not
* allow this, however.
*/
break;
diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c
index 5fffe7ab5ece..90431f12f831 100644
--- a/drivers/acpi/acpica/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -374,7 +374,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
* with the input value.
*
* When storing into an object the data is converted to the
- * target object type then stored in the object. This means
+ * target object type then stored in the object. This means
* that the target object type (for an initialized target) will
* not be changed by a store operation.
*
@@ -491,7 +491,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
acpi_ut_get_object_type_name(source_desc),
source_desc, node));
- /* No conversions for all other types. Just attach the source object */
+ /* No conversions for all other types. Just attach the source object */
status = acpi_ns_attach_object(node, source_desc,
source_desc->common.type);
diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c
index b35bed52e061..87153bbc4b43 100644
--- a/drivers/acpi/acpica/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exstoren - AML Interpreter object store support,
@@ -61,7 +60,7 @@ ACPI_MODULE_NAME("exstoren")
*
* RETURN: Status, resolved object in source_desc_ptr.
*
- * DESCRIPTION: Resolve an object. If the object is a reference, dereference
+ * DESCRIPTION: Resolve an object. If the object is a reference, dereference
* it and return the actual object in the source_desc_ptr.
*
******************************************************************************/
@@ -93,7 +92,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
/*
* Stores into a Field/Region or into a Integer/Buffer/String
- * are all essentially the same. This case handles the
+ * are all essentially the same. This case handles the
* "interchangeable" types Integer, String, and Buffer.
*/
if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
@@ -167,7 +166,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
*
* RETURN: Status
*
- * DESCRIPTION: "Store" an object to another object. This may include
+ * DESCRIPTION: "Store" an object to another object. This may include
* converting the source type to the target type (implicit
* conversion), and a copy of the value of the source to
* the target.
@@ -178,14 +177,14 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
* with the input value.
*
* When storing into an object the data is converted to the
- * target object type then stored in the object. This means
+ * target object type then stored in the object. This means
* that the target object type (for an initialized target) will
* not be changed by a store operation.
*
* This module allows destination types of Number, String,
* Buffer, and Package.
*
- * Assumes parameters are already validated. NOTE: source_desc
+ * Assumes parameters are already validated. NOTE: source_desc
* resolution (from a reference object) must be performed by
* the caller if necessary.
*
diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 53c248473547..b5f339cb1305 100644
--- a/drivers/acpi/acpica/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exstorob - AML Interpreter object store support, store to object
@@ -108,7 +107,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
#ifdef ACPI_OBSOLETE_BEHAVIOR
/*
* NOTE: ACPI versions up to 3.0 specified that the buffer must be
- * truncated if the string is smaller than the buffer. However, "other"
+ * truncated if the string is smaller than the buffer. However, "other"
* implementations of ACPI never did this and thus became the defacto
* standard. ACPI 3.0A changes this behavior such that the buffer
* is no longer truncated.
@@ -117,7 +116,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
/*
* OBSOLETE BEHAVIOR:
* If the original source was a string, we must truncate the buffer,
- * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
+ * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
* copy must not truncate the original buffer.
*/
if (original_src_type == ACPI_TYPE_STRING) {
diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c
index b760641e2fc6..c8a0ad5c1f55 100644
--- a/drivers/acpi/acpica/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exsystem - Interface to OS services
@@ -59,7 +58,7 @@ ACPI_MODULE_NAME("exsystem")
* RETURN: Status
*
* DESCRIPTION: Implements a semaphore wait with a check to see if the
- * semaphore is available immediately. If it is not, the
+ * semaphore is available immediately. If it is not, the
* interpreter is released before waiting.
*
******************************************************************************/
@@ -104,7 +103,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
* RETURN: Status
*
* DESCRIPTION: Implements a mutex wait with a check to see if the
- * mutex is available immediately. If it is not, the
+ * mutex is available immediately. If it is not, the
* interpreter is released before waiting.
*
******************************************************************************/
@@ -152,7 +151,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
* DESCRIPTION: Suspend running thread for specified amount of time.
* Note: ACPI specification requires that Stall() does not
* relinquish the processor, and delays longer than 100 usec
- * should use Sleep() instead. We allow stalls up to 255 usec
+ * should use Sleep() instead. We allow stalls up to 255 usec
* for compatibility with other interpreters and existing BIOSs.
*
******************************************************************************/
@@ -254,7 +253,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
* RETURN: Status
*
* DESCRIPTION: Provides an access point to perform synchronization operations
- * within the AML. This operation is a request to wait for an
+ * within the AML. This operation is a request to wait for an
* event.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c
index d1ab7917eed7..264d22d8018c 100644
--- a/drivers/acpi/acpica/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: exutils - interpreter/scanner utilities
@@ -45,12 +44,12 @@
/*
* DEFINE_AML_GLOBALS is tested in amlcode.h
* to determine whether certain global names should be "defined" or only
- * "declared" in the current compilation. This enhances maintainability
+ * "declared" in the current compilation. This enhances maintainability
* by enabling a single header file to embody all knowledge of the names
* in question.
*
* Exactly one module of any executable should #define DEFINE_GLOBALS
- * before #including the header files which use this convention. The
+ * before #including the header files which use this convention. The
* names in question will be defined and initialized in that module,
* and declared as extern in all other modules which #include those
* header files.
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index a1e71d0ef57b..90a9aea1cee9 100644
--- a/drivers/acpi/acpica/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
@@ -136,7 +135,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
*
* RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY
*
- * DESCRIPTION: Return current operating state of system. Determined by
+ * DESCRIPTION: Return current operating state of system. Determined by
* querying the SCI_EN bit.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index db4076580e2b..64560045052d 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: hwgpe - Low level GPE enable/disable/clear functions
@@ -339,7 +338,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
acpi_status
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block, void *context)
+ struct acpi_gpe_block_info * gpe_block,
+ void *context)
{
u32 i;
acpi_status status;
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
index 1455ddcdc32c..65bc3453a29c 100644
--- a/drivers/acpi/acpica/hwpci.c
+++ b/drivers/acpi/acpica/hwpci.c
@@ -259,7 +259,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
status = acpi_hw_get_pci_device_info(pci_id, info->device,
&bus_number, &is_bridge);
if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ return (status);
}
info = info->next;
@@ -271,7 +271,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function, status, bus_number, is_bridge));
- return_ACPI_STATUS(AE_OK);
+ return (AE_OK);
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index 4af6d20ef077..f4e57503576b 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -1,4 +1,3 @@
-
/*******************************************************************************
*
* Module Name: hwregs - Read/write access functions for the various ACPI
diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index b6411f16832f..bfdce22f3798 100644
--- a/drivers/acpi/acpica/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Name: hwtimer.c - ACPI Power Management Timer Interface
@@ -101,8 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks)
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- status =
- acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
+ status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
return_ACPI_STATUS(status);
}
@@ -129,7 +127,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer)
* a versatile and accurate timer.
*
* Note that this function accommodates only a single timer
- * rollover. Thus for 24-bit timers, this function should only
+ * rollover. Thus for 24-bit timers, this function should only
* be used for calculating durations less than ~4.6 seconds
* (~20 minutes for 32-bit timers) -- calculations below:
*
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index c99d546b217f..b6aae58299dc 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: hwvalid - I/O request validation
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 7bfd649d1996..05a154c3c9ac 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Module Name: hwxface - Public ACPICA hardware interfaces
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 0ff1ecea5c3a..ae443fe2ebf6 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -49,8 +49,7 @@
ACPI_MODULE_NAME("hwxfsleep")
/* Local prototypes */
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
/*
* Dispatch table used to efficiently branch to the various sleep
@@ -234,8 +233,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
* function.
*
******************************************************************************/
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
{
acpi_status status;
struct acpi_sleep_functions *sleep_functions =
@@ -369,8 +367,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
- status =
- acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
+ status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
return_ACPI_STATUS(status);
}
@@ -396,8 +393,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
status =
- acpi_hw_sleep_dispatch(sleep_state,
- ACPI_WAKE_PREP_FUNCTION_ID);
+ acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 23db53ce2293..d70eaf39dfdf 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -110,11 +110,11 @@ acpi_status acpi_ns_root_initialize(void)
status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
ACPI_IMODE_LOAD_PASS2,
ACPI_NS_NO_UPSEARCH, NULL, &new_node);
-
- if (ACPI_FAILURE(status) || (!new_node)) { /* Must be on same line for code converter */
+ if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not create predefined name %s",
init_val->name));
+ continue;
}
/*
@@ -179,8 +179,7 @@ acpi_status acpi_ns_root_initialize(void)
/* Build an object around the static string */
- obj_desc->string.length =
- (u32) ACPI_STRLEN(val);
+ obj_desc->string.length = (u32)ACPI_STRLEN(val);
obj_desc->string.pointer = val;
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
break;
diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index ac389e5bb594..15143c44f5e5 100644
--- a/drivers/acpi/acpica/nsalloc.c
+++ b/drivers/acpi/acpica/nsalloc.c
@@ -332,7 +332,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
*
* RETURN: None.
*
- * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
+ * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
* stored within the subtree.
*
******************************************************************************/
@@ -418,7 +418,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
* RETURN: Status
*
* DESCRIPTION: Delete entries within the namespace that are owned by a
- * specific ID. Used to delete entire ACPI tables. All
+ * specific ID. Used to delete entire ACPI tables. All
* reference counts are updated.
*
* MUTEX: Locks namespace during deletion walk.
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 2526aaf945ee..924b3c71473a 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -209,14 +209,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
"Invalid ACPI Object Type 0x%08X", type));
}
- if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
- this_node->name.integer =
- acpi_ut_repair_name(this_node->name.ascii);
-
- ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
- this_node->name.integer));
- }
-
acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
}
@@ -700,7 +692,7 @@ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
*
* PARAMETERS: search_base - Root of subtree to be dumped, or
* NS_ALL to dump the entire namespace
- * max_depth - Maximum depth of dump. Use INT_MAX
+ * max_depth - Maximum depth of dump. Use INT_MAX
* for an effectively unlimited depth.
*
* RETURN: None
diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c
index 95ffe8dfa1f1..4328e2adfeb9 100644
--- a/drivers/acpi/acpica/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -96,8 +96,8 @@ acpi_status acpi_ns_initialize_objects(void)
/* Walk entire namespace from the supplied root */
status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL,
- &info, NULL);
+ ACPI_UINT32_MAX, acpi_ns_init_one_object,
+ NULL, &info, NULL);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
}
diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c
index 76935ff29289..911f99127b99 100644
--- a/drivers/acpi/acpica/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -80,8 +80,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
/*
* Parse the table and load the namespace with all named
- * objects found within. Control methods are NOT parsed
- * at this time. In fact, the control methods cannot be
+ * objects found within. Control methods are NOT parsed
+ * at this time. In fact, the control methods cannot be
* parsed until the entire namespace is loaded, because
* if a control method makes a forward reference (call)
* to another control method, we can't continue parsing
@@ -122,7 +122,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
}
/*
- * Now we can parse the control methods. We always parse
+ * Now we can parse the control methods. We always parse
* them here for a sanity check, and if configured for
* just-in-time parsing, we delete the control method
* parse trees.
@@ -166,7 +166,7 @@ acpi_status acpi_ns_load_namespace(void)
}
/*
- * Load the namespace. The DSDT is required,
+ * Load the namespace. The DSDT is required,
* but the SSDT and PSDT tables are optional.
*/
status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
@@ -283,7 +283,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
* RETURN: Status
*
* DESCRIPTION: Shrinks the namespace, typically in response to an undocking
- * event. Deletes an entire subtree starting from (and
+ * event. Deletes an entire subtree starting from (and
* including) the given handle.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index 96e0eb609bb4..55a175eadcc3 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -195,7 +195,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
ACPI_ERROR((AE_INFO,
"Invalid Namespace Node (%p) while traversing namespace",
next_node));
- return 0;
+ return (0);
}
size += ACPI_PATH_SEGMENT_LENGTH;
next_node = next_node->parent;
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c
index d6c9a3cc6716..e69f7fa2579d 100644
--- a/drivers/acpi/acpica/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("nsobject")
* RETURN: Status
*
* DESCRIPTION: Record the given object as the value associated with the
- * name whose acpi_handle is passed. If Object is NULL
+ * name whose acpi_handle is passed. If Object is NULL
* and Type is ACPI_TYPE_ANY, set the name as having no value.
* Note: Future may require that the Node->Flags field be passed
* as a parameter.
@@ -133,7 +133,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
((struct acpi_namespace_node *)object)->object) {
/*
* Value passed is a name handle and that name has a
- * non-null value. Use that name's value and type.
+ * non-null value. Use that name's value and type.
*/
obj_desc = ((struct acpi_namespace_node *)object)->object;
object_type = ((struct acpi_namespace_node *)object)->type;
@@ -321,7 +321,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union
*
* RETURN: Status
*
- * DESCRIPTION: Low-level attach data. Create and attach a Data object.
+ * DESCRIPTION: Low-level attach data. Create and attach a Data object.
*
******************************************************************************/
@@ -377,7 +377,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node,
*
* RETURN: Status
*
- * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
+ * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
* is responsible for the actual data.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c
index ec7ba2d3463c..233f756d5cfa 100644
--- a/drivers/acpi/acpica/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -168,11 +168,11 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
/*
* AML Parse, pass 1
*
- * In this pass, we load most of the namespace. Control methods
- * are not parsed until later. A parse tree is not created. Instead,
- * each Parser Op subtree is deleted when it is finished. This saves
+ * In this pass, we load most of the namespace. Control methods
+ * are not parsed until later. A parse tree is not created. Instead,
+ * each Parser Op subtree is deleted when it is finished. This saves
* a great deal of memory, and allows a small cache of parse objects
- * to service the entire parse. The second pass of the parse then
+ * to service the entire parse. The second pass of the parse then
* performs another complete parse of the AML.
*/
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c
index 456cc859f869..1d2d8ffc1bc5 100644
--- a/drivers/acpi/acpica/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -314,22 +314,7 @@ acpi_ns_search_and_enter(u32 target_name,
* this problem, and we want to be able to enable ACPI support for them,
* even though there are a few bad names.
*/
- if (!acpi_ut_valid_acpi_name(target_name)) {
- target_name =
- acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
-
- /* Report warning only if in strict mode or debug mode */
-
- if (!acpi_gbl_enable_interpreter_slack) {
- ACPI_WARNING((AE_INFO,
- "Found bad character(s) in name, repaired: [%4.4s]\n",
- ACPI_CAST_PTR(char, &target_name)));
- } else {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Found bad character(s) in name, repaired: [%4.4s]\n",
- ACPI_CAST_PTR(char, &target_name)));
- }
- }
+ acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
/* Try to find the name in the namespace level specified by the caller */
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index ef753a41e087..b5b4cb72a8a8 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -530,7 +530,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
((num_segments > 0) ? (num_segments - 1) : 0) + 1;
/*
- * Check to see if we're still in bounds. If not, there's a problem
+ * Check to see if we're still in bounds. If not, there's a problem
* with internal_name (invalid format).
*/
if (required_length > internal_name_length) {
@@ -557,10 +557,14 @@ acpi_ns_externalize_name(u32 internal_name_length,
(*converted_name)[j++] = '.';
}
- (*converted_name)[j++] = internal_name[names_index++];
- (*converted_name)[j++] = internal_name[names_index++];
- (*converted_name)[j++] = internal_name[names_index++];
- (*converted_name)[j++] = internal_name[names_index++];
+ /* Copy and validate the 4-char name segment */
+
+ ACPI_MOVE_NAME(&(*converted_name)[j],
+ &internal_name[names_index]);
+ acpi_ut_repair_name(&(*converted_name)[j]);
+
+ j += ACPI_NAME_SIZE;
+ names_index += ACPI_NAME_SIZE;
}
}
@@ -681,7 +685,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
* \ (backslash) and ^ (carat) prefixes, and the
* . (period) to separate segments are supported.
* prefix_node - Root of subtree to be searched, or NS_ALL for the
- * root of the name space. If Name is fully
+ * root of the name space. If Name is fully
* qualified (first s8 is '\'), the passed value
* of Scope will not be accessed.
* flags - Used to indicate whether to perform upsearch or
@@ -689,7 +693,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
* return_node - Where the Node is returned
*
* DESCRIPTION: Look up a name relative to a given scope and return the
- * corresponding Node. NOTE: Scope can be null.
+ * corresponding Node. NOTE: Scope can be null.
*
* MUTEX: Locks namespace
*
diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 730bccc5e7f7..0483877f26b8 100644
--- a/drivers/acpi/acpica/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -60,8 +60,8 @@ ACPI_MODULE_NAME("nswalk")
* RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if
* none is found.
*
- * DESCRIPTION: Return the next peer node within the namespace. If Handle
- * is valid, Scope is ignored. Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ * is valid, Scope is ignored. Otherwise, the first node
* within Scope is returned.
*
******************************************************************************/
@@ -97,8 +97,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
* RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if
* none is found.
*
- * DESCRIPTION: Return the next peer node within the namespace. If Handle
- * is valid, Scope is ignored. Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ * is valid, Scope is ignored. Otherwise, the first node
* within Scope is returned.
*
******************************************************************************/
@@ -305,7 +305,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
/*
* Depth first search: Attempt to go down another level in the
- * namespace if we are allowed to. Don't go any further if we have
+ * namespace if we are allowed to. Don't go any further if we have
* reached the caller specified maximum depth or if the user
* function has specified that the maximum depth has been reached.
*/
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index 9692e6702333..d6a9f77972b6 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -61,16 +61,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
* PARAMETERS: handle - Object handle (optional)
* pathname - Object pathname (optional)
* external_params - List of parameters to pass to method,
- * terminated by NULL. May be NULL
+ * terminated by NULL. May be NULL
* if no parameters are being passed.
* return_buffer - Where to put method's return value (if
- * any). If NULL, no value is returned.
+ * any). If NULL, no value is returned.
* return_type - Expected type of return object
*
* RETURN: Status
*
* DESCRIPTION: Find and evaluate the given object, passing the given
- * parameters if necessary. One of "Handle" or "Pathname" must
+ * parameters if necessary. One of "Handle" or "Pathname" must
* be valid (non-null)
*
******************************************************************************/
@@ -155,15 +155,15 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
* PARAMETERS: handle - Object handle (optional)
* pathname - Object pathname (optional)
* external_params - List of parameters to pass to method,
- * terminated by NULL. May be NULL
+ * terminated by NULL. May be NULL
* if no parameters are being passed.
* return_buffer - Where to put method's return value (if
- * any). If NULL, no value is returned.
+ * any). If NULL, no value is returned.
*
* RETURN: Status
*
* DESCRIPTION: Find and evaluate the given object, passing the given
- * parameters if necessary. One of "Handle" or "Pathname" must
+ * parameters if necessary. One of "Handle" or "Pathname" must
* be valid (non-null)
*
******************************************************************************/
@@ -542,15 +542,15 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
- struct acpica_device_id *hid;
- struct acpica_device_id_list *cid;
+ struct acpi_pnp_device_id *hid;
+ struct acpi_pnp_device_id_list *cid;
u32 i;
u8 found;
int no_match;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
- return (status);
+ return_ACPI_STATUS(status);
}
node = acpi_ns_validate_handle(obj_handle);
@@ -656,7 +656,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
* DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
* starting (and ending) at the object specified by start_handle.
* The user_function is called whenever an object of type
- * Device is found. If the user function returns
+ * Device is found. If the user function returns
* a non-zero value, the search is terminated immediately and this
* value is returned to the caller.
*
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 08e9610b34ca..811c6f13f476 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -53,8 +53,8 @@
ACPI_MODULE_NAME("nsxfname")
/* Local prototypes */
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
- struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+ struct acpi_pnp_device_id *source,
char *string_area);
/******************************************************************************
@@ -69,8 +69,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
* RETURN: Status
*
* DESCRIPTION: This routine will search for a caller specified name in the
- * name space. The caller can restrict the search region by
- * specifying a non NULL parent. The parent value is itself a
+ * name space. The caller can restrict the search region by
+ * specifying a non NULL parent. The parent value is itself a
* namespace handle.
*
******************************************************************************/
@@ -149,7 +149,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle)
* RETURN: Pointer to a string containing the fully qualified Name.
*
* DESCRIPTION: This routine returns the fully qualified name associated with
- * the Handle parameter. This and the acpi_pathname_to_handle are
+ * the Handle parameter. This and the acpi_pathname_to_handle are
* complementary functions.
*
******************************************************************************/
@@ -202,8 +202,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
/* Just copy the ACPI name from the Node and zero terminate it */
- ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
- ACPI_NAME_SIZE);
+ ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node));
((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
status = AE_OK;
@@ -219,20 +218,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_name)
*
* FUNCTION: acpi_ns_copy_device_id
*
- * PARAMETERS: dest - Pointer to the destination DEVICE_ID
- * source - Pointer to the source DEVICE_ID
+ * PARAMETERS: dest - Pointer to the destination PNP_DEVICE_ID
+ * source - Pointer to the source PNP_DEVICE_ID
* string_area - Pointer to where to copy the dest string
*
* RETURN: Pointer to the next string area
*
- * DESCRIPTION: Copy a single DEVICE_ID, including the string data.
+ * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
*
******************************************************************************/
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
- struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+ struct acpi_pnp_device_id *source,
char *string_area)
{
- /* Create the destination DEVICE_ID */
+
+ /* Create the destination PNP_DEVICE_ID */
dest->string = string_area;
dest->length = source->length;
@@ -256,8 +256,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
* namespace node and possibly by running several standard
* control methods (Such as in the case of a device.)
*
- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
- * _ADR, _sx_w, and _sx_d methods.
+ * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
+ * _STA, _ADR, _sx_w, and _sx_d methods.
*
* Note: Allocates the return buffer, must be freed by the caller.
*
@@ -269,9 +269,10 @@ acpi_get_object_info(acpi_handle handle,
{
struct acpi_namespace_node *node;
struct acpi_device_info *info;
- struct acpica_device_id_list *cid_list = NULL;
- struct acpica_device_id *hid = NULL;
- struct acpica_device_id *uid = NULL;
+ struct acpi_pnp_device_id_list *cid_list = NULL;
+ struct acpi_pnp_device_id *hid = NULL;
+ struct acpi_pnp_device_id *uid = NULL;
+ struct acpi_pnp_device_id *sub = NULL;
char *next_id_string;
acpi_object_type type;
acpi_name name;
@@ -316,7 +317,7 @@ acpi_get_object_info(acpi_handle handle,
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Device/Processor objects only:
- * Run the Device _HID, _UID, and _CID methods.
+ * Run the Device _HID, _UID, _SUB, and _CID methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
@@ -339,6 +340,14 @@ acpi_get_object_info(acpi_handle handle,
valid |= ACPI_VALID_UID;
}
+ /* Execute the Device._SUB method */
+
+ status = acpi_ut_execute_SUB(node, &sub);
+ if (ACPI_SUCCESS(status)) {
+ info_size += sub->length;
+ valid |= ACPI_VALID_SUB;
+ }
+
/* Execute the Device._CID method */
status = acpi_ut_execute_CID(node, &cid_list);
@@ -348,7 +357,7 @@ acpi_get_object_info(acpi_handle handle,
info_size +=
(cid_list->list_size -
- sizeof(struct acpica_device_id_list));
+ sizeof(struct acpi_pnp_device_id_list));
valid |= ACPI_VALID_CID;
}
}
@@ -418,16 +427,17 @@ acpi_get_object_info(acpi_handle handle,
next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
if (cid_list) {
- /* Point past the CID DEVICE_ID array */
+ /* Point past the CID PNP_DEVICE_ID array */
next_id_string +=
((acpi_size) cid_list->count *
- sizeof(struct acpica_device_id));
+ sizeof(struct acpi_pnp_device_id));
}
/*
- * Copy the HID, UID, and CIDs to the return buffer. The variable-length
- * strings are copied to the reserved area at the end of the buffer.
+ * Copy the HID, UID, SUB, and CIDs to the return buffer.
+ * The variable-length strings are copied to the reserved area
+ * at the end of the buffer.
*
* For HID and CID, check if the ID is a PCI Root Bridge.
*/
@@ -445,6 +455,11 @@ acpi_get_object_info(acpi_handle handle,
uid, next_id_string);
}
+ if (sub) {
+ next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
+ sub, next_id_string);
+ }
+
if (cid_list) {
info->compatible_id_list.count = cid_list->count;
info->compatible_id_list.list_size = cid_list->list_size;
@@ -481,6 +496,9 @@ acpi_get_object_info(acpi_handle handle,
if (uid) {
ACPI_FREE(uid);
}
+ if (sub) {
+ ACPI_FREE(sub);
+ }
if (cid_list) {
ACPI_FREE(cid_list);
}
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 6766fc4f088f..9d029dac6b64 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -220,8 +220,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent)
*
* RETURN: Status
*
- * DESCRIPTION: Return the next peer object within the namespace. If Handle is
- * valid, Scope is ignored. Otherwise, the first object within
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ * valid, Scope is ignored. Otherwise, the first object within
* Scope is returned.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
index 844464c4f901..cb79e2d4d743 100644
--- a/drivers/acpi/acpica/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -120,7 +120,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
* RETURN: Pointer to end-of-package +1
*
* DESCRIPTION: Get next package length and return a pointer past the end of
- * the package. Consumes the package length field
+ * the package. Consumes the package length field
*
******************************************************************************/
@@ -147,8 +147,8 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
* RETURN: Pointer to the start of the name string (pointer points into
* the AML.
*
- * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
- * prefix characters. Set parser state to point past the string.
+ * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
+ * prefix characters. Set parser state to point past the string.
* (Name is consumed from the AML.)
*
******************************************************************************/
@@ -220,7 +220,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
*
* DESCRIPTION: Get next name (if method call, return # of required args).
* Names are looked up in the internal namespace to determine
- * if the name represents a control method. If a method
+ * if the name represents a control method. If a method
* is found, the number of arguments to the method is returned.
* This information is critical for parsing to continue correctly.
*
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 799162c1b6df..5607805aab26 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -133,18 +133,46 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
case AML_CLASS_UNKNOWN:
- /* The opcode is unrecognized. Just skip unknown opcodes */
+ /* The opcode is unrecognized. Complain and skip unknown opcodes */
- ACPI_ERROR((AE_INFO,
- "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring",
- walk_state->opcode, walk_state->parser_state.aml,
- walk_state->aml_offset));
+ if (walk_state->pass_number == 2) {
+ ACPI_ERROR((AE_INFO,
+ "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
+ walk_state->opcode,
+ (u32)(walk_state->aml_offset +
+ sizeof(struct acpi_table_header))));
- ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128);
+ ACPI_DUMP_BUFFER(walk_state->parser_state.aml - 16, 48);
- /* Assume one-byte bad opcode */
+#ifdef ACPI_ASL_COMPILER
+ /*
+ * This is executed for the disassembler only. Output goes
+ * to the disassembled ASL output file.
+ */
+ acpi_os_printf
+ ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
+ walk_state->opcode,
+ (u32)(walk_state->aml_offset +
+ sizeof(struct acpi_table_header)));
+
+ /* Dump the context surrounding the invalid opcode */
+
+ acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
+ aml - 16), 48, DB_BYTE_DISPLAY,
+ walk_state->aml_offset +
+ sizeof(struct acpi_table_header) -
+ 16);
+ acpi_os_printf(" */\n");
+#endif
+ }
+
+ /* Increment past one-byte or two-byte opcode */
walk_state->parser_state.aml++;
+ if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */
+ walk_state->parser_state.aml++;
+ }
+
return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
default:
@@ -519,11 +547,18 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
if ((op_info->class ==
AML_CLASS_EXECUTE) && (!arg)) {
ACPI_WARNING((AE_INFO,
- "Detected an unsupported executable opcode "
- "at module-level: [0x%.4X] at table offset 0x%.4X",
- op->common.aml_opcode,
- (u32)((aml_op_start - walk_state->parser_state.aml_start)
- + sizeof(struct acpi_table_header))));
+ "Unsupported module-level executable opcode "
+ "0x%.2X at table offset 0x%.4X",
+ op->common.
+ aml_opcode,
+ (u32)
+ (ACPI_PTR_DIFF
+ (aml_op_start,
+ walk_state->
+ parser_state.
+ aml_start) +
+ sizeof(struct
+ acpi_table_header))));
}
}
break;
@@ -843,8 +878,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
*op = NULL;
}
- ACPI_PREEMPTION_POINT();
-
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
index ed1d457bd5ca..1793d934aa30 100644
--- a/drivers/acpi/acpica/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -59,7 +59,7 @@ static const u8 acpi_gbl_argument_count[] =
*
* DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands>
* The name is a simple ascii string, the operand specifier is an
- * ascii string with one letter per operand. The letter specifies
+ * ascii string with one letter per operand. The letter specifies
* the operand type.
*
******************************************************************************/
@@ -183,7 +183,7 @@ static const u8 acpi_gbl_argument_count[] =
******************************************************************************/
/*
- * Master Opcode information table. A summary of everything we know about each
+ * Master Opcode information table. A summary of everything we know about each
* opcode, all in one place.
*/
const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
@@ -392,10 +392,12 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
/* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CONSTANT),
/* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
@@ -495,7 +497,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
AML_NSNODE | AML_NAMED | AML_DEFER),
/* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
/* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
AML_TYPE_NAMED_NO_OBJ,
@@ -519,12 +522,13 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
AML_TYPE_NAMED_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD),
/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
- ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD |
- AML_DEFER),
+ ACPI_TYPE_LOCAL_BANK_FIELD,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_FIELD | AML_DEFER),
/* Internal opcodes that map to invalid AML opcodes */
@@ -632,7 +636,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
/* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
AML_TYPE_NAMED_NO_OBJ,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE),
/* ACPI 3.0 opcodes */
@@ -695,7 +700,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
/*
* This table is indexed by the second opcode of the extended opcode
- * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
+ * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
*/
static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
/* 0 1 2 3 4 5 6 7 */
diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c
index 01985703bb98..2494caf47755 100644
--- a/drivers/acpi/acpica/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -43,9 +43,9 @@
/*
* Parse the AML and build an operation tree as most interpreters,
- * like Perl, do. Parsing is done by hand rather than with a YACC
+ * like Perl, do. Parsing is done by hand rather than with a YACC
* generated parser to tightly constrain stack and dynamic memory
- * usage. At the same time, parsing is kept flexible and the code
+ * usage. At the same time, parsing is kept flexible and the code
* fairly compact by parsing based on a list of AML opcode
* templates in aml_op_info[]
*/
@@ -379,7 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
case AE_CTRL_FALSE:
/*
* Either an IF/WHILE Predicate was false or we encountered a BREAK
- * opcode. In both cases, we do not execute the rest of the
+ * opcode. In both cases, we do not execute the rest of the
* package; We simply close out the parent (finishing the walk of
* this branch of the tree) and continue execution at the parent
* level.
@@ -459,8 +459,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
/* Executing a control method - additional cleanup */
- acpi_ds_terminate_control_method(
- walk_state->method_desc, walk_state);
+ acpi_ds_terminate_control_method(walk_state->
+ method_desc,
+ walk_state);
}
acpi_ds_delete_walk_state(walk_state);
@@ -487,7 +488,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
acpi_gbl_current_walk_list = thread;
/*
- * Execute the walk loop as long as there is a valid Walk State. This
+ * Execute the walk loop as long as there is a valid Walk State. This
* handles nested control method invocations without recursion.
*/
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state));
diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c
index 8736ad5f04d3..4137dcb352d1 100644
--- a/drivers/acpi/acpica/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -108,7 +108,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
* RETURN: Pointer to the new Op, null on failure
*
* DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
- * opcode. A cache of opcodes is available for the pure
+ * opcode. A cache of opcodes is available for the pure
* GENERIC_OP, since this is by far the most commonly used.
*
******************************************************************************/
@@ -164,7 +164,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
*
* RETURN: None.
*
- * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
+ * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
* or actually free it.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index de12469d1c9c..147feb6aa2a0 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -457,6 +457,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
* Get the number of vendor data bytes
*/
extra_struct_bytes = resource_length;
+
+ /*
+ * There is already one byte included in the minimum
+ * descriptor size. If there are extra struct bytes,
+ * subtract one from the count.
+ */
+ if (extra_struct_bytes) {
+ extra_struct_bytes--;
+ }
break;
case ACPI_RESOURCE_NAME_END_TAG:
@@ -601,7 +610,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
/*
* Calculate the size of the return buffer.
* The base size is the number of elements * the sizes of the
- * structures. Additional space for the strings is added below.
+ * structures. Additional space for the strings is added below.
* The minus one is to subtract the size of the u8 Source[1]
* member because it is added below.
*
@@ -664,8 +673,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
(*sub_object_list)->string.
length + 1);
} else {
- temp_size_needed +=
- acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
+ temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
}
} else {
/*
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c
index 46b5324b22d6..8b64db9a3fd2 100644
--- a/drivers/acpi/acpica/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -109,7 +109,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
ACPI_ERROR((AE_INFO,
"Invalid/unsupported resource descriptor: Type 0x%2.2X",
resource_index));
- return (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
/* Convert the AML byte stream resource to a local resource struct */
@@ -200,7 +200,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
ACPI_ERROR((AE_INFO,
"Invalid/unsupported resource descriptor: Type 0x%2.2X",
resource->type));
- return (AE_AML_INVALID_RESOURCE_TYPE);
+ return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
}
status = acpi_rs_convert_resource_to_aml(resource,
diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c
index 57deae166577..77d1db29a725 100644
--- a/drivers/acpi/acpica/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -77,7 +77,7 @@ acpi_tb_find_table(char *signature,
/* Normalize the input strings */
ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header));
- ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE);
+ ACPI_MOVE_NAME(header.signature, signature);
ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE);
ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 70f9d787c82c..f540ae462925 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -526,6 +526,8 @@ void acpi_tb_terminate(void)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+ return_VOID;
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index b6cea30da638..285e24b97382 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -354,7 +354,7 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
sum = (u8) (sum + *(buffer++));
}
- return sum;
+ return (sum);
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index 21101262e47a..f5632780421d 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -236,7 +236,7 @@ acpi_get_table_header(char *signature,
sizeof(struct
acpi_table_header));
if (!header) {
- return AE_NO_MEMORY;
+ return (AE_NO_MEMORY);
}
ACPI_MEMCPY(out_table_header, header,
sizeof(struct acpi_table_header));
@@ -244,7 +244,7 @@ acpi_get_table_header(char *signature,
sizeof(struct
acpi_table_header));
} else {
- return AE_NOT_FOUND;
+ return (AE_NOT_FOUND);
}
} else {
ACPI_MEMCPY(out_table_header,
diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c
index f87cc63e69a1..a5e1e4e47098 100644
--- a/drivers/acpi/acpica/tbxfload.c
+++ b/drivers/acpi/acpica/tbxfload.c
@@ -211,7 +211,7 @@ static acpi_status acpi_tb_load_namespace(void)
* DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
* be a valid ACPI table with a valid ACPI table header.
* Note1: Mainly intended to support hotplug addition of SSDTs.
- * Note2: Does not copy the incoming table. User is reponsible
+ * Note2: Does not copy the incoming table. User is responsible
* to ensure that the table is not deleted or unmapped.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 74e720800037..28f330230f99 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -67,7 +67,6 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
{
- ACPI_FUNCTION_ENTRY();
/*
* The signature and checksum must both be correct
@@ -108,7 +107,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
* RETURN: Status, RSDP physical address
*
* DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
- * pointer structure. If it is found, set *RSDP to point to it.
+ * pointer structure. If it is found, set *RSDP to point to it.
*
* NOTE1: The RSDP must be either in the first 1K of the Extended
* BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
new file mode 100644
index 000000000000..e1d40ed26390
--- /dev/null
+++ b/drivers/acpi/acpica/utcache.c
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *
+ * Module Name: utcache - local cache allocation routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("utcache")
+
+#ifdef ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_create_cache
+ *
+ * PARAMETERS: cache_name - Ascii name for the cache
+ * object_size - Size of each cached object
+ * max_depth - Maximum depth of the cache (in objects)
+ * return_cache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+acpi_status
+acpi_os_create_cache(char *cache_name,
+ u16 object_size,
+ u16 max_depth, struct acpi_memory_list ** return_cache)
+{
+ struct acpi_memory_list *cache;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache_name || !return_cache || (object_size < 16)) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* Create the cache object */
+
+ cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+ if (!cache) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Populate the cache object and return it */
+
+ ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+ cache->link_offset = 8;
+ cache->list_name = cache_name;
+ cache->object_size = object_size;
+ cache->max_depth = max_depth;
+
+ *return_cache = cache;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_purge_cache
+ *
+ * PARAMETERS: cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+{
+ char *next;
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Walk the list of objects in this cache */
+
+ while (cache->list_head) {
+
+ /* Delete and unlink one cached state object */
+
+ next = *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)cache->
+ list_head)[cache->
+ link_offset])));
+ ACPI_FREE(cache->list_head);
+
+ cache->list_head = next;
+ cache->current_depth--;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_delete_cache
+ *
+ * PARAMETERS: cache - Handle to cache object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ * cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /* Purge all objects in the cache */
+
+ status = acpi_os_purge_cache(cache);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Now we can delete the cache object */
+
+ acpi_os_free(cache);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_release_object
+ *
+ * PARAMETERS: cache - Handle to cache object
+ * object - The object to be released
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ * the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!cache || !object) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* If cache is full, just free this object */
+
+ if (cache->current_depth >= cache->max_depth) {
+ ACPI_FREE(object);
+ ACPI_MEM_TRACKING(cache->total_freed++);
+ }
+
+ /* Otherwise put this object back into the cache */
+
+ else {
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Mark the object as cached */
+
+ ACPI_MEMSET(object, 0xCA, cache->object_size);
+ ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
+
+ /* Put the object at the head of the cache list */
+
+ *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)object)[cache->
+ link_offset]))) =
+ cache->list_head;
+ cache->list_head = object;
+ cache->current_depth++;
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_os_acquire_object
+ *
+ * PARAMETERS: cache - Handle to cache object
+ *
+ * RETURN: the acquired object. NULL on error
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ * the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(struct acpi_memory_list *cache)
+{
+ acpi_status status;
+ void *object;
+
+ ACPI_FUNCTION_NAME(os_acquire_object);
+
+ if (!cache) {
+ return (NULL);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ ACPI_MEM_TRACKING(cache->requests++);
+
+ /* Check the cache first */
+
+ if (cache->list_head) {
+
+ /* There is an object available, use it */
+
+ object = cache->list_head;
+ cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
+ &(((char *)
+ object)[cache->
+ link_offset])));
+
+ cache->current_depth--;
+
+ ACPI_MEM_TRACKING(cache->hits++);
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Object %p from %s cache\n", object,
+ cache->list_name));
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ /* Clear (zero) the previously used Object */
+
+ ACPI_MEMSET(object, 0, cache->object_size);
+ } else {
+ /* The cache is empty, create a new object */
+
+ ACPI_MEM_TRACKING(cache->total_allocated++);
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+ if ((cache->total_allocated - cache->total_freed) >
+ cache->max_occupied) {
+ cache->max_occupied =
+ cache->total_allocated - cache->total_freed;
+ }
+#endif
+
+ /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
+
+ status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+ if (ACPI_FAILURE(status)) {
+ return (NULL);
+ }
+
+ object = ACPI_ALLOCATE_ZEROED(cache->object_size);
+ if (!object) {
+ return (NULL);
+ }
+ }
+
+ return (object);
+}
+#endif /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/acpica/utclib.c b/drivers/acpi/acpica/utclib.c
new file mode 100644
index 000000000000..19ea4755aa73
--- /dev/null
+++ b/drivers/acpi/acpica/utclib.c
@@ -0,0 +1,749 @@
+/******************************************************************************
+ *
+ * Module Name: cmclib - Local implementation of C library functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+/*
+ * These implementations of standard C Library routines can optionally be
+ * used if a C library is not available. In general, they are less efficient
+ * than an inline or assembly implementation
+ */
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("cmclib")
+
+#ifndef ACPI_USE_SYSTEM_CLIBRARY
+#define NEGATIVE 1
+#define POSITIVE 0
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_memcmp (memcmp)
+ *
+ * PARAMETERS: buffer1 - First Buffer
+ * buffer2 - Second Buffer
+ * count - Maximum # of bytes to compare
+ *
+ * RETURN: Index where Buffers mismatched, or 0 if Buffers matched
+ *
+ * DESCRIPTION: Compare two Buffers, with a maximum length
+ *
+ ******************************************************************************/
+int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count)
+{
+
+ return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*buffer1 -
+ (unsigned char)*buffer2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_memcpy (memcpy)
+ *
+ * PARAMETERS: dest - Target of the copy
+ * src - Source buffer to copy
+ * count - Number of bytes to copy
+ *
+ * RETURN: Dest
+ *
+ * DESCRIPTION: Copy arbitrary bytes of memory
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count)
+{
+ char *new = (char *)dest;
+ char *old = (char *)src;
+
+ while (count) {
+ *new = *old;
+ new++;
+ old++;
+ count--;
+ }
+
+ return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_memset (memset)
+ *
+ * PARAMETERS: dest - Buffer to set
+ * value - Value to set each byte of memory
+ * count - Number of bytes to set
+ *
+ * RETURN: Dest
+ *
+ * DESCRIPTION: Initialize a buffer to a known value.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memset(void *dest, u8 value, acpi_size count)
+{
+ char *new = (char *)dest;
+
+ while (count) {
+ *new = (char)value;
+ new++;
+ count--;
+ }
+
+ return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strlen (strlen)
+ *
+ * PARAMETERS: string - Null terminated string
+ *
+ * RETURN: Length
+ *
+ * DESCRIPTION: Returns the length of the input string
+ *
+ ******************************************************************************/
+
+acpi_size acpi_ut_strlen(const char *string)
+{
+ u32 length = 0;
+
+ /* Count the string until a null is encountered */
+
+ while (*string) {
+ length++;
+ string++;
+ }
+
+ return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strcpy (strcpy)
+ *
+ * PARAMETERS: dst_string - Target of the copy
+ * src_string - The source string to copy
+ *
+ * RETURN: dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcpy(char *dst_string, const char *src_string)
+{
+ char *string = dst_string;
+
+ /* Move bytes brute force */
+
+ while (*src_string) {
+ *string = *src_string;
+
+ string++;
+ src_string++;
+ }
+
+ /* Null terminate */
+
+ *string = 0;
+ return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strncpy (strncpy)
+ *
+ * PARAMETERS: dst_string - Target of the copy
+ * src_string - The source string to copy
+ * count - Maximum # of bytes to copy
+ *
+ * RETURN: dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string, with a maximum length
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncpy(char *dst_string, const char *src_string, acpi_size count)
+{
+ char *string = dst_string;
+
+ /* Copy the string */
+
+ for (string = dst_string;
+ count && (count--, (*string++ = *src_string++));) {;
+ }
+
+ /* Pad with nulls if necessary */
+
+ while (count--) {
+ *string = 0;
+ string++;
+ }
+
+ /* Return original pointer */
+
+ return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strcmp (strcmp)
+ *
+ * PARAMETERS: string1 - First string
+ * string2 - Second string
+ *
+ * RETURN: Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings
+ *
+ ******************************************************************************/
+
+int acpi_ut_strcmp(const char *string1, const char *string2)
+{
+
+ for (; (*string1 == *string2); string2++) {
+ if (!*string1++) {
+ return (0);
+ }
+ }
+
+ return ((unsigned char)*string1 - (unsigned char)*string2);
+}
+
+#ifdef ACPI_FUTURE_IMPLEMENTATION
+/* Not used at this time */
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strchr (strchr)
+ *
+ * PARAMETERS: string - Search string
+ * ch - character to search for
+ *
+ * RETURN: Ptr to char or NULL if not found
+ *
+ * DESCRIPTION: Search a string for a character
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strchr(const char *string, int ch)
+{
+
+ for (; (*string); string++) {
+ if ((*string) == (char)ch) {
+ return ((char *)string);
+ }
+ }
+
+ return (NULL);
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strncmp (strncmp)
+ *
+ * PARAMETERS: string1 - First string
+ * string2 - Second string
+ * count - Maximum # of bytes to compare
+ *
+ * RETURN: Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings, with a maximum length
+ *
+ ******************************************************************************/
+
+int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count)
+{
+
+ for (; count-- && (*string1 == *string2); string2++) {
+ if (!*string1++) {
+ return (0);
+ }
+ }
+
+ return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*string1 -
+ (unsigned char)*string2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strcat (Strcat)
+ *
+ * PARAMETERS: dst_string - Target of the copy
+ * src_string - The source string to copy
+ *
+ * RETURN: dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcat(char *dst_string, const char *src_string)
+{
+ char *string;
+
+ /* Find end of the destination string */
+
+ for (string = dst_string; *string++;) {;
+ }
+
+ /* Concatenate the string */
+
+ for (--string; (*string++ = *src_string++);) {;
+ }
+
+ return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strncat (strncat)
+ *
+ * PARAMETERS: dst_string - Target of the copy
+ * src_string - The source string to copy
+ * count - Maximum # of bytes to copy
+ *
+ * RETURN: dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string,
+ * with a maximum count.
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncat(char *dst_string, const char *src_string, acpi_size count)
+{
+ char *string;
+
+ if (count) {
+
+ /* Find end of the destination string */
+
+ for (string = dst_string; *string++;) {;
+ }
+
+ /* Concatenate the string */
+
+ for (--string; (*string++ = *src_string++) && --count;) {;
+ }
+
+ /* Null terminate if necessary */
+
+ if (!count) {
+ *string = 0;
+ }
+ }
+
+ return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strstr (strstr)
+ *
+ * PARAMETERS: string1 - Target string
+ * string2 - Substring to search for
+ *
+ * RETURN: Where substring match starts, Null if no match found
+ *
+ * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
+ * full implementation of strstr, only sufficient for command
+ * matching
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strstr(char *string1, char *string2)
+{
+ char *string;
+
+ if (acpi_ut_strlen(string2) > acpi_ut_strlen(string1)) {
+ return (NULL);
+ }
+
+ /* Walk entire string, comparing the letters */
+
+ for (string = string1; *string2;) {
+ if (*string2 != *string) {
+ return (NULL);
+ }
+
+ string2++;
+ string++;
+ }
+
+ return (string1);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strtoul (strtoul)
+ *
+ * PARAMETERS: string - Null terminated string
+ * terminater - Where a pointer to the terminating byte is
+ * returned
+ * base - Radix of the string
+ *
+ * RETURN: Converted value
+ *
+ * DESCRIPTION: Convert a string into a 32-bit unsigned value.
+ * Note: use acpi_ut_strtoul64 for 64-bit integers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base)
+{
+ u32 converted = 0;
+ u32 index;
+ u32 sign;
+ const char *string_start;
+ u32 return_value = 0;
+ acpi_status status = AE_OK;
+
+ /*
+ * Save the value of the pointer to the buffer's first
+ * character, save the current errno value, and then
+ * skip over any white space in the buffer:
+ */
+ string_start = string;
+ while (ACPI_IS_SPACE(*string) || *string == '\t') {
+ ++string;
+ }
+
+ /*
+ * The buffer may contain an optional plus or minus sign.
+ * If it does, then skip over it but remember what is was:
+ */
+ if (*string == '-') {
+ sign = NEGATIVE;
+ ++string;
+ } else if (*string == '+') {
+ ++string;
+ sign = POSITIVE;
+ } else {
+ sign = POSITIVE;
+ }
+
+ /*
+ * If the input parameter Base is zero, then we need to
+ * determine if it is octal, decimal, or hexadecimal:
+ */
+ if (base == 0) {
+ if (*string == '0') {
+ if (acpi_ut_to_lower(*(++string)) == 'x') {
+ base = 16;
+ ++string;
+ } else {
+ base = 8;
+ }
+ } else {
+ base = 10;
+ }
+ } else if (base < 2 || base > 36) {
+ /*
+ * The specified Base parameter is not in the domain of
+ * this function:
+ */
+ goto done;
+ }
+
+ /*
+ * For octal and hexadecimal bases, skip over the leading
+ * 0 or 0x, if they are present.
+ */
+ if (base == 8 && *string == '0') {
+ string++;
+ }
+
+ if (base == 16 &&
+ *string == '0' && acpi_ut_to_lower(*(++string)) == 'x') {
+ string++;
+ }
+
+ /*
+ * Main loop: convert the string to an unsigned long:
+ */
+ while (*string) {
+ if (ACPI_IS_DIGIT(*string)) {
+ index = (u32)((u8)*string - '0');
+ } else {
+ index = (u32)acpi_ut_to_upper(*string);
+ if (ACPI_IS_UPPER(index)) {
+ index = index - 'A' + 10;
+ } else {
+ goto done;
+ }
+ }
+
+ if (index >= base) {
+ goto done;
+ }
+
+ /*
+ * Check to see if value is out of range:
+ */
+
+ if (return_value > ((ACPI_UINT32_MAX - (u32)index) / (u32)base)) {
+ status = AE_ERROR;
+ return_value = 0; /* reset */
+ } else {
+ return_value *= base;
+ return_value += index;
+ converted = 1;
+ }
+
+ ++string;
+ }
+
+ done:
+ /*
+ * If appropriate, update the caller's pointer to the next
+ * unconverted character in the buffer.
+ */
+ if (terminator) {
+ if (converted == 0 && return_value == 0 && string != NULL) {
+ *terminator = (char *)string_start;
+ } else {
+ *terminator = (char *)string;
+ }
+ }
+
+ if (status == AE_ERROR) {
+ return_value = ACPI_UINT32_MAX;
+ }
+
+ /*
+ * If a minus sign was present, then "the conversion is negated":
+ */
+ if (sign == NEGATIVE) {
+ return_value = (ACPI_UINT32_MAX - return_value) + 1;
+ }
+
+ return (return_value);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_to_upper (TOUPPER)
+ *
+ * PARAMETERS: c - Character to convert
+ *
+ * RETURN: Converted character as an int
+ *
+ * DESCRIPTION: Convert character to uppercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_upper(int c)
+{
+
+ return (ACPI_IS_LOWER(c) ? ((c) - 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_to_lower (TOLOWER)
+ *
+ * PARAMETERS: c - Character to convert
+ *
+ * RETURN: Converted character as an int
+ *
+ * DESCRIPTION: Convert character to lowercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_lower(int c)
+{
+
+ return (ACPI_IS_UPPER(c) ? ((c) + 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: is* functions
+ *
+ * DESCRIPTION: is* functions use the ctype table below
+ *
+ ******************************************************************************/
+
+const u8 _acpi_ctype[257] = {
+ _ACPI_CN, /* 0x00 0 NUL */
+ _ACPI_CN, /* 0x01 1 SOH */
+ _ACPI_CN, /* 0x02 2 STX */
+ _ACPI_CN, /* 0x03 3 ETX */
+ _ACPI_CN, /* 0x04 4 EOT */
+ _ACPI_CN, /* 0x05 5 ENQ */
+ _ACPI_CN, /* 0x06 6 ACK */
+ _ACPI_CN, /* 0x07 7 BEL */
+ _ACPI_CN, /* 0x08 8 BS */
+ _ACPI_CN | _ACPI_SP, /* 0x09 9 TAB */
+ _ACPI_CN | _ACPI_SP, /* 0x0A 10 LF */
+ _ACPI_CN | _ACPI_SP, /* 0x0B 11 VT */
+ _ACPI_CN | _ACPI_SP, /* 0x0C 12 FF */
+ _ACPI_CN | _ACPI_SP, /* 0x0D 13 CR */
+ _ACPI_CN, /* 0x0E 14 SO */
+ _ACPI_CN, /* 0x0F 15 SI */
+ _ACPI_CN, /* 0x10 16 DLE */
+ _ACPI_CN, /* 0x11 17 DC1 */
+ _ACPI_CN, /* 0x12 18 DC2 */
+ _ACPI_CN, /* 0x13 19 DC3 */
+ _ACPI_CN, /* 0x14 20 DC4 */
+ _ACPI_CN, /* 0x15 21 NAK */
+ _ACPI_CN, /* 0x16 22 SYN */
+ _ACPI_CN, /* 0x17 23 ETB */
+ _ACPI_CN, /* 0x18 24 CAN */
+ _ACPI_CN, /* 0x19 25 EM */
+ _ACPI_CN, /* 0x1A 26 SUB */
+ _ACPI_CN, /* 0x1B 27 ESC */
+ _ACPI_CN, /* 0x1C 28 FS */
+ _ACPI_CN, /* 0x1D 29 GS */
+ _ACPI_CN, /* 0x1E 30 RS */
+ _ACPI_CN, /* 0x1F 31 US */
+ _ACPI_XS | _ACPI_SP, /* 0x20 32 ' ' */
+ _ACPI_PU, /* 0x21 33 '!' */
+ _ACPI_PU, /* 0x22 34 '"' */
+ _ACPI_PU, /* 0x23 35 '#' */
+ _ACPI_PU, /* 0x24 36 '$' */
+ _ACPI_PU, /* 0x25 37 '%' */
+ _ACPI_PU, /* 0x26 38 '&' */
+ _ACPI_PU, /* 0x27 39 ''' */
+ _ACPI_PU, /* 0x28 40 '(' */
+ _ACPI_PU, /* 0x29 41 ')' */
+ _ACPI_PU, /* 0x2A 42 '*' */
+ _ACPI_PU, /* 0x2B 43 '+' */
+ _ACPI_PU, /* 0x2C 44 ',' */
+ _ACPI_PU, /* 0x2D 45 '-' */
+ _ACPI_PU, /* 0x2E 46 '.' */
+ _ACPI_PU, /* 0x2F 47 '/' */
+ _ACPI_XD | _ACPI_DI, /* 0x30 48 '0' */
+ _ACPI_XD | _ACPI_DI, /* 0x31 49 '1' */
+ _ACPI_XD | _ACPI_DI, /* 0x32 50 '2' */
+ _ACPI_XD | _ACPI_DI, /* 0x33 51 '3' */
+ _ACPI_XD | _ACPI_DI, /* 0x34 52 '4' */
+ _ACPI_XD | _ACPI_DI, /* 0x35 53 '5' */
+ _ACPI_XD | _ACPI_DI, /* 0x36 54 '6' */
+ _ACPI_XD | _ACPI_DI, /* 0x37 55 '7' */
+ _ACPI_XD | _ACPI_DI, /* 0x38 56 '8' */
+ _ACPI_XD | _ACPI_DI, /* 0x39 57 '9' */
+ _ACPI_PU, /* 0x3A 58 ':' */
+ _ACPI_PU, /* 0x3B 59 ';' */
+ _ACPI_PU, /* 0x3C 60 '<' */
+ _ACPI_PU, /* 0x3D 61 '=' */
+ _ACPI_PU, /* 0x3E 62 '>' */
+ _ACPI_PU, /* 0x3F 63 '?' */
+ _ACPI_PU, /* 0x40 64 '@' */
+ _ACPI_XD | _ACPI_UP, /* 0x41 65 'A' */
+ _ACPI_XD | _ACPI_UP, /* 0x42 66 'B' */
+ _ACPI_XD | _ACPI_UP, /* 0x43 67 'C' */
+ _ACPI_XD | _ACPI_UP, /* 0x44 68 'D' */
+ _ACPI_XD | _ACPI_UP, /* 0x45 69 'E' */
+ _ACPI_XD | _ACPI_UP, /* 0x46 70 'F' */
+ _ACPI_UP, /* 0x47 71 'G' */
+ _ACPI_UP, /* 0x48 72 'H' */
+ _ACPI_UP, /* 0x49 73 'I' */
+ _ACPI_UP, /* 0x4A 74 'J' */
+ _ACPI_UP, /* 0x4B 75 'K' */
+ _ACPI_UP, /* 0x4C 76 'L' */
+ _ACPI_UP, /* 0x4D 77 'M' */
+ _ACPI_UP, /* 0x4E 78 'N' */
+ _ACPI_UP, /* 0x4F 79 'O' */
+ _ACPI_UP, /* 0x50 80 'P' */
+ _ACPI_UP, /* 0x51 81 'Q' */
+ _ACPI_UP, /* 0x52 82 'R' */
+ _ACPI_UP, /* 0x53 83 'S' */
+ _ACPI_UP, /* 0x54 84 'T' */
+ _ACPI_UP, /* 0x55 85 'U' */
+ _ACPI_UP, /* 0x56 86 'V' */
+ _ACPI_UP, /* 0x57 87 'W' */
+ _ACPI_UP, /* 0x58 88 'X' */
+ _ACPI_UP, /* 0x59 89 'Y' */
+ _ACPI_UP, /* 0x5A 90 'Z' */
+ _ACPI_PU, /* 0x5B 91 '[' */
+ _ACPI_PU, /* 0x5C 92 '\' */
+ _ACPI_PU, /* 0x5D 93 ']' */
+ _ACPI_PU, /* 0x5E 94 '^' */
+ _ACPI_PU, /* 0x5F 95 '_' */
+ _ACPI_PU, /* 0x60 96 '`' */
+ _ACPI_XD | _ACPI_LO, /* 0x61 97 'a' */
+ _ACPI_XD | _ACPI_LO, /* 0x62 98 'b' */
+ _ACPI_XD | _ACPI_LO, /* 0x63 99 'c' */
+ _ACPI_XD | _ACPI_LO, /* 0x64 100 'd' */
+ _ACPI_XD | _ACPI_LO, /* 0x65 101 'e' */
+ _ACPI_XD | _ACPI_LO, /* 0x66 102 'f' */
+ _ACPI_LO, /* 0x67 103 'g' */
+ _ACPI_LO, /* 0x68 104 'h' */
+ _ACPI_LO, /* 0x69 105 'i' */
+ _ACPI_LO, /* 0x6A 106 'j' */
+ _ACPI_LO, /* 0x6B 107 'k' */
+ _ACPI_LO, /* 0x6C 108 'l' */
+ _ACPI_LO, /* 0x6D 109 'm' */
+ _ACPI_LO, /* 0x6E 110 'n' */
+ _ACPI_LO, /* 0x6F 111 'o' */
+ _ACPI_LO, /* 0x70 112 'p' */
+ _ACPI_LO, /* 0x71 113 'q' */
+ _ACPI_LO, /* 0x72 114 'r' */
+ _ACPI_LO, /* 0x73 115 's' */
+ _ACPI_LO, /* 0x74 116 't' */
+ _ACPI_LO, /* 0x75 117 'u' */
+ _ACPI_LO, /* 0x76 118 'v' */
+ _ACPI_LO, /* 0x77 119 'w' */
+ _ACPI_LO, /* 0x78 120 'x' */
+ _ACPI_LO, /* 0x79 121 'y' */
+ _ACPI_LO, /* 0x7A 122 'z' */
+ _ACPI_PU, /* 0x7B 123 '{' */
+ _ACPI_PU, /* 0x7C 124 '|' */
+ _ACPI_PU, /* 0x7D 125 '}' */
+ _ACPI_PU, /* 0x7E 126 '~' */
+ _ACPI_CN, /* 0x7F 127 DEL */
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 to 0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 to 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 to 0xAF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 to 0xBF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 to 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 to 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 to 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 to 0xFF */
+ 0 /* 0x100 */
+};
+
+#endif /* ACPI_USE_SYSTEM_CLIBRARY */
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index e810894149ae..5d95166245ae 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -47,8 +47,9 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utdebug")
+
#ifdef ACPI_DEBUG_OUTPUT
-static acpi_thread_id acpi_gbl_prev_thread_id;
+static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF;
static char *acpi_gbl_fn_entry_str = "----Entry";
static char *acpi_gbl_fn_exit_str = "----Exit-";
@@ -109,7 +110,7 @@ void acpi_ut_track_stack_ptr(void)
* RETURN: Updated pointer to the function name
*
* DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
- * This allows compiler macros such as __func__ to be used
+ * This allows compiler macros such as __FUNCTION__ to be used
* with no change to the debug output.
*
******************************************************************************/
@@ -222,7 +223,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print)
*
* RETURN: None
*
- * DESCRIPTION: Print message with no headers. Has same interface as
+ * DESCRIPTION: Print message with no headers. Has same interface as
* debug_print so that the same macros can be used.
*
******************************************************************************/
@@ -258,7 +259,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print_raw)
*
* RETURN: None
*
- * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level
*
******************************************************************************/
@@ -290,7 +291,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
*
* RETURN: None
*
- * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level
*
******************************************************************************/
@@ -299,6 +300,7 @@ acpi_ut_trace_ptr(u32 line_number,
const char *function_name,
const char *module_name, u32 component_id, void *pointer)
{
+
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
@@ -319,7 +321,7 @@ acpi_ut_trace_ptr(u32 line_number,
*
* RETURN: None
*
- * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level
*
******************************************************************************/
@@ -350,7 +352,7 @@ acpi_ut_trace_str(u32 line_number,
*
* RETURN: None
*
- * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level
*
******************************************************************************/
@@ -380,7 +382,7 @@ acpi_ut_trace_u32(u32 line_number,
*
* RETURN: None
*
- * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level
*
******************************************************************************/
@@ -412,7 +414,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
*
* RETURN: None
*
- * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level. Prints exit status also.
*
******************************************************************************/
@@ -453,7 +455,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
*
* RETURN: None
*
- * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level. Prints exit value also.
*
******************************************************************************/
@@ -485,7 +487,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
*
* RETURN: None
*
- * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
* set in debug_level. Prints exit value also.
*
******************************************************************************/
@@ -511,7 +513,7 @@ acpi_ut_ptr_exit(u32 line_number,
* PARAMETERS: buffer - Buffer to dump
* count - Amount to dump, in bytes
* display - BYTE, WORD, DWORD, or QWORD display
- * component_ID - Caller's component ID
+ * offset - Beginning buffer offset (display only)
*
* RETURN: None
*
@@ -519,7 +521,7 @@ acpi_ut_ptr_exit(u32 line_number,
*
******************************************************************************/
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset)
{
u32 i = 0;
u32 j;
@@ -541,7 +543,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
/* Print current offset */
- acpi_os_printf("%6.4X: ", i);
+ acpi_os_printf("%6.4X: ", (base_offset + i));
/* Print 16 hex chars */
@@ -623,7 +625,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_dump_buffer
+ * FUNCTION: acpi_ut_debug_dump_buffer
*
* PARAMETERS: buffer - Buffer to dump
* count - Amount to dump, in bytes
@@ -636,7 +638,8 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
*
******************************************************************************/
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id)
{
/* Only dump the buffer if tracing is enabled */
@@ -646,5 +649,5 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
return;
}
- acpi_ut_dump_buffer2(buffer, count, display);
+ acpi_ut_dump_buffer(buffer, count, display, 0);
}
diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c
index 5d84e1954575..774c3aefbf5d 100644
--- a/drivers/acpi/acpica/utids.c
+++ b/drivers/acpi/acpica/utids.c
@@ -67,10 +67,10 @@ ACPI_MODULE_NAME("utids")
******************************************************************************/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
- struct acpica_device_id **return_id)
+ struct acpi_pnp_device_id **return_id)
{
union acpi_operand_object *obj_desc;
- struct acpica_device_id *hid;
+ struct acpi_pnp_device_id *hid;
u32 length;
acpi_status status;
@@ -94,16 +94,17 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
/* Allocate a buffer for the HID */
hid =
- ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
(acpi_size) length);
if (!hid) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Area for the string starts after DEVICE_ID struct */
+ /* Area for the string starts after PNP_DEVICE_ID struct */
- hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id));
+ hid->string =
+ ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
/* Convert EISAID to a string or simply copy existing string */
@@ -126,6 +127,73 @@ cleanup:
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_execute_SUB
+ *
+ * PARAMETERS: device_node - Node for the device
+ * return_id - Where the _SUB is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Executes the _SUB control method that returns the subsystem
+ * ID of the device. The _SUB value is always a string containing
+ * either a valid PNP or ACPI ID.
+ *
+ * NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+ struct acpi_pnp_device_id **return_id)
+{
+ union acpi_operand_object *obj_desc;
+ struct acpi_pnp_device_id *sub;
+ u32 length;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ut_execute_SUB);
+
+ status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
+ ACPI_BTYPE_STRING, &obj_desc);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Get the size of the String to be returned, includes null terminator */
+
+ length = obj_desc->string.length + 1;
+
+ /* Allocate a buffer for the SUB */
+
+ sub =
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
+ (acpi_size) length);
+ if (!sub) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ /* Area for the string starts after PNP_DEVICE_ID struct */
+
+ sub->string =
+ ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
+
+ /* Simply copy existing string */
+
+ ACPI_STRCPY(sub->string, obj_desc->string.pointer);
+ sub->length = length;
+ *return_id = sub;
+
+ cleanup:
+
+ /* On exit, we must delete the return object */
+
+ acpi_ut_remove_reference(obj_desc);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_execute_UID
*
* PARAMETERS: device_node - Node for the device
@@ -144,10 +212,10 @@ cleanup:
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
- struct acpica_device_id **return_id)
+ struct acpi_pnp_device_id **return_id)
{
union acpi_operand_object *obj_desc;
- struct acpica_device_id *uid;
+ struct acpi_pnp_device_id *uid;
u32 length;
acpi_status status;
@@ -171,16 +239,17 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
/* Allocate a buffer for the UID */
uid =
- ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
(acpi_size) length);
if (!uid) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Area for the string starts after DEVICE_ID struct */
+ /* Area for the string starts after PNP_DEVICE_ID struct */
- uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id));
+ uid->string =
+ ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
/* Convert an Integer to string, or just copy an existing string */
@@ -226,11 +295,11 @@ cleanup:
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
- struct acpica_device_id_list **return_cid_list)
+ struct acpi_pnp_device_id_list **return_cid_list)
{
union acpi_operand_object **cid_objects;
union acpi_operand_object *obj_desc;
- struct acpica_device_id_list *cid_list;
+ struct acpi_pnp_device_id_list *cid_list;
char *next_id_string;
u32 string_area_size;
u32 length;
@@ -288,11 +357,12 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
/*
* Now that we know the length of the CIDs, allocate return buffer:
* 1) Size of the base structure +
- * 2) Size of the CID DEVICE_ID array +
+ * 2) Size of the CID PNP_DEVICE_ID array +
* 3) Size of the actual CID strings
*/
- cid_list_size = sizeof(struct acpica_device_id_list) +
- ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size;
+ cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
+ ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
+ string_area_size;
cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
if (!cid_list) {
@@ -300,10 +370,10 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
goto cleanup;
}
- /* Area for CID strings starts after the CID DEVICE_ID array */
+ /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
- ((acpi_size) count * sizeof(struct acpica_device_id));
+ ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
/* Copy/convert the CIDs to the return buffer */
diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c
index d88a8aaab2a6..49563674833a 100644
--- a/drivers/acpi/acpica/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -81,7 +81,7 @@ typedef union uint64_overlay {
* RETURN: Status (Checks for divide-by-zero)
*
* DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
- * divide and modulo. The result is a 64-bit quotient and a
+ * divide and modulo. The result is a 64-bit quotient and a
* 32-bit remainder.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 33c6cf7ff467..9286a69eb9aa 100644
--- a/drivers/acpi/acpica/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -41,8 +41,6 @@
* POSSIBILITY OF SUCH DAMAGES.
*/
-#include <linux/module.h>
-
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
@@ -201,8 +199,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
*/
acpi_gbl_owner_id_mask[j] |= (1 << k);
- acpi_gbl_last_owner_id_index = (u8) j;
- acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+ acpi_gbl_last_owner_id_index = (u8)j;
+ acpi_gbl_next_owner_id_offset = (u8)(k + 1);
/*
* Construct encoded ID from the index and bit position
@@ -252,7 +250,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
* control method or unloading a table. Either way, we would
* ignore any error anyway.
*
- * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
*
******************************************************************************/
@@ -339,6 +337,73 @@ void acpi_ut_strupr(char *src_string)
return;
}
+#ifdef ACPI_ASL_COMPILER
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_strlwr (strlwr)
+ *
+ * PARAMETERS: src_string - The source string to convert
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Convert string to lowercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void acpi_ut_strlwr(char *src_string)
+{
+ char *string;
+
+ ACPI_FUNCTION_ENTRY();
+
+ if (!src_string) {
+ return;
+ }
+
+ /* Walk entire string, lowercasing the letters */
+
+ for (string = src_string; *string; string++) {
+ *string = (char)ACPI_TOLOWER(*string);
+ }
+
+ return;
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ut_stricmp
+ *
+ * PARAMETERS: string1 - first string to compare
+ * string2 - second string to compare
+ *
+ * RETURN: int that signifies string relationship. Zero means strings
+ * are equal.
+ *
+ * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
+ * strings with no case sensitivity)
+ *
+ ******************************************************************************/
+
+int acpi_ut_stricmp(char *string1, char *string2)
+{
+ int c1;
+ int c2;
+
+ do {
+ c1 = tolower((int)*string1);
+ c2 = tolower((int)*string2);
+
+ string1++;
+ string2++;
+ }
+ while ((c1 == c2) && (c1));
+
+ return (c1 - c2);
+}
+#endif
+
/*******************************************************************************
*
* FUNCTION: acpi_ut_print_string
@@ -469,8 +534,8 @@ u32 acpi_ut_dword_byte_swap(u32 value)
* RETURN: None
*
* DESCRIPTION: Set the global integer bit width based upon the revision
- * of the DSDT. For Revision 1 and 0, Integers are 32 bits.
- * For Revision 2 and above, Integers are 64 bits. Yes, this
+ * of the DSDT. For Revision 1 and 0, Integers are 32 bits.
+ * For Revision 2 and above, Integers are 64 bits. Yes, this
* makes a difference.
*
******************************************************************************/
@@ -606,7 +671,7 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position)
*
* RETURN: TRUE if the name is valid, FALSE otherwise
*
- * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
+ * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
* 1) Upper case alpha
* 2) numeric
* 3) underscore
@@ -638,29 +703,59 @@ u8 acpi_ut_valid_acpi_name(u32 name)
* RETURN: Repaired version of the name
*
* DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
- * return the new name.
+ * return the new name. NOTE: the Name parameter must reside in
+ * read/write memory, cannot be a const.
+ *
+ * An ACPI Name must consist of valid ACPI characters. We will repair the name
+ * if necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
*
******************************************************************************/
-acpi_name acpi_ut_repair_name(char *name)
+void acpi_ut_repair_name(char *name)
{
- u32 i;
- char new_name[ACPI_NAME_SIZE];
+ u32 i;
+ u8 found_bad_char = FALSE;
+ u32 original_name;
+
+ ACPI_FUNCTION_NAME(ut_repair_name);
+
+ ACPI_MOVE_NAME(&original_name, name);
+
+ /* Check each character in the name */
for (i = 0; i < ACPI_NAME_SIZE; i++) {
- new_name[i] = name[i];
+ if (acpi_ut_valid_acpi_char(name[i], i)) {
+ continue;
+ }
/*
* Replace a bad character with something printable, yet technically
* still invalid. This prevents any collisions with existing "good"
* names in the namespace.
*/
- if (!acpi_ut_valid_acpi_char(name[i], i)) {
- new_name[i] = '*';
- }
+ name[i] = '*';
+ found_bad_char = TRUE;
}
- return (*(u32 *) new_name);
+ if (found_bad_char) {
+
+ /* Report warning only if in strict mode or debug mode */
+
+ if (!acpi_gbl_enable_interpreter_slack) {
+ ACPI_WARNING((AE_INFO,
+ "Found bad character(s) in name, repaired: [%4.4s]\n",
+ name));
+ } else {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Found bad character(s) in name, repaired: [%4.4s]\n",
+ name));
+ }
+ }
}
/*******************************************************************************
@@ -681,7 +776,7 @@ acpi_name acpi_ut_repair_name(char *name)
*
******************************************************************************/
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
{
u32 this_digit = 0;
u64 return_value = 0;
@@ -754,14 +849,14 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
/* Convert ASCII 0-9 to Decimal value */
- this_digit = ((u8) * string) - '0';
+ this_digit = ((u8)*string) - '0';
} else if (base == 10) {
/* Digit is out of range; possible in to_integer case only */
term = 1;
} else {
- this_digit = (u8) ACPI_TOUPPER(*string);
+ this_digit = (u8)ACPI_TOUPPER(*string);
if (ACPI_IS_XDIGIT((char)this_digit)) {
/* Convert ASCII Hex char to value */
@@ -788,8 +883,9 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
valid_digits++;
- if (sign_of0x && ((valid_digits > 16)
- || ((valid_digits > 8) && mode32))) {
+ if (sign_of0x
+ && ((valid_digits > 16)
+ || ((valid_digits > 8) && mode32))) {
/*
* This is to_integer operation case.
* No any restrictions for string-to-integer conversion,
@@ -800,7 +896,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
/* Divide the digit into the correct position */
- (void)acpi_ut_short_divide((dividend - (u64) this_digit),
+ (void)acpi_ut_short_divide((dividend - (u64)this_digit),
base, &quotient, NULL);
if (return_value > quotient) {
@@ -890,7 +986,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
******************************************************************************/
acpi_status
-acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
+acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
void *target_object,
acpi_pkg_callback walk_callback, void *context)
{
@@ -917,10 +1013,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
/*
* Check for:
- * 1) An uninitialized package element. It is completely
+ * 1) An uninitialized package element. It is completely
* legal to declare a package and leave it uninitialized
* 2) Not an internal object - can be a namespace node instead
- * 3) Any type other than a package. Packages are handled in else
+ * 3) Any type other than a package. Packages are handled in else
* case below.
*/
if ((!this_source_obj) ||
@@ -939,7 +1035,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
state->pkg.source_object->package.count) {
/*
* We've handled all of the objects at this level, This means
- * that we have just completed a package. That package may
+ * that we have just completed a package. That package may
* have contained one or more packages itself.
*
* Delete this state and pop the previous state (package).
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 296baa676bc5..5ccf57c0d87e 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -193,6 +193,8 @@ static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
acpi_gbl_mutex_info[mutex_id].mutex = NULL;
acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+ return_VOID;
}
/*******************************************************************************
@@ -226,9 +228,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
/*
* Mutex debug code, for internal debugging only.
*
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than or equal to this one. If so, the thread has violated
- * the mutex ordering rule. This indicates a coding error somewhere in
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than or equal to this one. If so, the thread has violated
+ * the mutex ordering rule. This indicates a coding error somewhere in
* the ACPI subsystem code.
*/
for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
@@ -319,9 +321,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
/*
* Mutex debug code, for internal debugging only.
*
- * Deadlock prevention. Check if this thread owns any mutexes of value
- * greater than this one. If so, the thread has violated the mutex
- * ordering rule. This indicates a coding error somewhere in
+ * Deadlock prevention. Check if this thread owns any mutexes of value
+ * greater than this one. If so, the thread has violated the mutex
+ * ordering rule. This indicates a coding error somewhere in
* the ACPI subsystem code.
*/
for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c
index 655f0799a391..5c52ca78f6fa 100644
--- a/drivers/acpi/acpica/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -77,7 +77,7 @@ acpi_ut_get_element_length(u8 object_type,
*
* NOTE: We always allocate the worst-case object descriptor because
* these objects are cached, and we want them to be
- * one-size-satisifies-any-request. This in itself may not be
+ * one-size-satisifies-any-request. This in itself may not be
* the most memory efficient, but the efficiency of the object
* cache should more than make up for this!
*
@@ -370,9 +370,9 @@ u8 acpi_ut_valid_internal_object(void *object)
* line_number - Caller's line number (for error output)
* component_id - Caller's component ID (for error output)
*
- * RETURN: Pointer to newly allocated object descriptor. Null on error
+ * RETURN: Pointer to newly allocated object descriptor. Null on error
*
- * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
+ * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
* error conditions.
*
******************************************************************************/
@@ -554,7 +554,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
/*
* Account for the space required by the object rounded up to the next
- * multiple of the machine word size. This keeps each object aligned
+ * multiple of the machine word size. This keeps each object aligned
* on a machine word boundary. (preventing alignment faults on some
* machines.)
*/
diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c
index a1c988260073..cee0473ba813 100644
--- a/drivers/acpi/acpica/utstate.c
+++ b/drivers/acpi/acpica/utstate.c
@@ -147,7 +147,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
*
* RETURN: The new state object. NULL on failure.
*
- * DESCRIPTION: Create a generic state object. Attempt to obtain one from
+ * DESCRIPTION: Create a generic state object. Attempt to obtain one from
* the global state cache; If none available, create a new one.
*
******************************************************************************/
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
new file mode 100644
index 000000000000..a424a9e3fea4
--- /dev/null
+++ b/drivers/acpi/acpica/uttrack.c
@@ -0,0 +1,692 @@
+/******************************************************************************
+ *
+ * Module Name: uttrack - Memory allocation tracking routines (debug only)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * 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 MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+/*
+ * These procedures are used for tracking memory leaks in the subsystem, and
+ * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
+ *
+ * Each memory allocation is tracked via a doubly linked list. Each
+ * element contains the caller's component, module name, function name, and
+ * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
+ * acpi_ut_track_allocation to add an element to the list; deletion
+ * occurs in the body of acpi_ut_free.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+#define _COMPONENT ACPI_UTILITIES
+ACPI_MODULE_NAME("uttrack")
+
+/* Local prototypes */
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+ acpi_debug_mem_block
+ *allocation);
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
+ acpi_size size,
+ u8 alloc_type,
+ u32 component, const char *module, u32 line);
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
+ u32 component, const char *module, u32 line);
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_create_list
+ *
+ * PARAMETERS: cache_name - Ascii name for the cache
+ * object_size - Size of each cached object
+ * return_cache - Where the new cache object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a local memory list for tracking purposed
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_create_list(char *list_name,
+ u16 object_size, struct acpi_memory_list **return_cache)
+{
+ struct acpi_memory_list *cache;
+
+ cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+ if (!cache) {
+ return (AE_NO_MEMORY);
+ }
+
+ ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+
+ cache->list_name = list_name;
+ cache->object_size = object_size;
+
+ *return_cache = cache;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_allocate_and_track
+ *
+ * PARAMETERS: size - Size of the allocation
+ * component - Component type of caller
+ * module - Source file name of caller
+ * line - Line number of caller
+ *
+ * RETURN: Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: The subsystem's equivalent of malloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_and_track(acpi_size size,
+ u32 component, const char *module, u32 line)
+{
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
+
+ allocation =
+ acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
+ if (!allocation) {
+ return (NULL);
+ }
+
+ status = acpi_ut_track_allocation(allocation, size,
+ ACPI_MEM_MALLOC, component, module,
+ line);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_free(allocation);
+ return (NULL);
+ }
+
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->total_size += (u32)size;
+ acpi_gbl_global_list->current_total_size += (u32)size;
+ if (acpi_gbl_global_list->current_total_size >
+ acpi_gbl_global_list->max_occupied) {
+ acpi_gbl_global_list->max_occupied =
+ acpi_gbl_global_list->current_total_size;
+ }
+
+ return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_allocate_zeroed_and_track
+ *
+ * PARAMETERS: size - Size of the allocation
+ * component - Component type of caller
+ * module - Source file name of caller
+ * line - Line number of caller
+ *
+ * RETURN: Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: Subsystem equivalent of calloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
+ u32 component,
+ const char *module, u32 line)
+{
+ struct acpi_debug_mem_block *allocation;
+ acpi_status status;
+
+ allocation =
+ acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header),
+ component, module, line);
+ if (!allocation) {
+
+ /* Report allocation error */
+
+ ACPI_ERROR((module, line,
+ "Could not allocate size %u", (u32)size));
+ return (NULL);
+ }
+
+ status = acpi_ut_track_allocation(allocation, size,
+ ACPI_MEM_CALLOC, component, module,
+ line);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_free(allocation);
+ return (NULL);
+ }
+
+ acpi_gbl_global_list->total_allocated++;
+ acpi_gbl_global_list->total_size += (u32)size;
+ acpi_gbl_global_list->current_total_size += (u32)size;
+ if (acpi_gbl_global_list->current_total_size >
+ acpi_gbl_global_list->max_occupied) {
+ acpi_gbl_global_list->max_occupied =
+ acpi_gbl_global_list->current_total_size;
+ }
+
+ return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_free_and_track
+ *
+ * PARAMETERS: allocation - Address of the memory to deallocate
+ * component - Component type of caller
+ * module - Source file name of caller
+ * line - Line number of caller
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Frees the memory at Allocation
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_free_and_track(void *allocation,
+ u32 component, const char *module, u32 line)
+{
+ struct acpi_debug_mem_block *debug_block;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
+
+ if (NULL == allocation) {
+ ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
+
+ return_VOID;
+ }
+
+ debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
+ (((char *)allocation) -
+ sizeof(struct acpi_debug_mem_header)));
+
+ acpi_gbl_global_list->total_freed++;
+ acpi_gbl_global_list->current_total_size -= debug_block->size;
+
+ status = acpi_ut_remove_allocation(debug_block,
+ component, module, line);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
+ }
+
+ acpi_os_free(debug_block);
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_find_allocation
+ *
+ * PARAMETERS: allocation - Address of allocated memory
+ *
+ * RETURN: Three cases:
+ * 1) List is empty, NULL is returned.
+ * 2) Element was found. Returns Allocation parameter.
+ * 3) Element was not found. Returns position where it should be
+ * inserted into the list.
+ *
+ * DESCRIPTION: Searches for an element in the global allocation tracking list.
+ * If the element is not found, returns the location within the
+ * list where the element should be inserted.
+ *
+ * Note: The list is ordered by larger-to-smaller addresses.
+ *
+ * This global list is used to detect memory leaks in ACPICA as
+ * well as other issues such as an attempt to release the same
+ * internal object more than once. Although expensive as far
+ * as cpu time, this list is much more helpful for finding these
+ * types of issues than using memory leak detectors outside of
+ * the ACPICA code.
+ *
+ ******************************************************************************/
+
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+ acpi_debug_mem_block
+ *allocation)
+{
+ struct acpi_debug_mem_block *element;
+
+ element = acpi_gbl_global_list->list_head;
+ if (!element) {
+ return (NULL);
+ }
+
+ /*
+ * Search for the address.
+ *
+ * Note: List is ordered by larger-to-smaller addresses, on the
+ * assumption that a new allocation usually has a larger address
+ * than previous allocations.
+ */
+ while (element > allocation) {
+
+ /* Check for end-of-list */
+
+ if (!element->next) {
+ return (element);
+ }
+
+ element = element->next;
+ }
+
+ if (element == allocation) {
+ return (element);
+ }
+
+ return (element->previous);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_track_allocation
+ *
+ * PARAMETERS: allocation - Address of allocated memory
+ * size - Size of the allocation
+ * alloc_type - MEM_MALLOC or MEM_CALLOC
+ * component - Component type of caller
+ * module - Source file name of caller
+ * line - Line number of caller
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Inserts an element into the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
+ acpi_size size,
+ u8 alloc_type,
+ u32 component, const char *module, u32 line)
+{
+ struct acpi_memory_list *mem_list;
+ struct acpi_debug_mem_block *element;
+ acpi_status status = AE_OK;
+
+ ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
+
+ if (acpi_gbl_disable_mem_tracking) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ mem_list = acpi_gbl_global_list;
+ status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /*
+ * Search the global list for this address to make sure it is not
+ * already present. This will catch several kinds of problems.
+ */
+ element = acpi_ut_find_allocation(allocation);
+ if (element == allocation) {
+ ACPI_ERROR((AE_INFO,
+ "UtTrackAllocation: Allocation (%p) already present in global list!",
+ allocation));
+ goto unlock_and_exit;
+ }
+
+ /* Fill in the instance data */
+
+ allocation->size = (u32)size;
+ allocation->alloc_type = alloc_type;
+ allocation->component = component;
+ allocation->line = line;
+
+ ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
+ allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
+
+ if (!element) {
+
+ /* Insert at list head */
+
+ if (mem_list->list_head) {
+ ((struct acpi_debug_mem_block *)(mem_list->list_head))->
+ previous = allocation;
+ }
+
+ allocation->next = mem_list->list_head;
+ allocation->previous = NULL;
+
+ mem_list->list_head = allocation;
+ } else {
+ /* Insert after element */
+
+ allocation->next = element->next;
+ allocation->previous = element;
+
+ if (element->next) {
+ (element->next)->previous = allocation;
+ }
+
+ element->next = allocation;
+ }
+
+ unlock_and_exit:
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_remove_allocation
+ *
+ * PARAMETERS: allocation - Address of allocated memory
+ * component - Component type of caller
+ * module - Source file name of caller
+ * line - Line number of caller
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Deletes an element from the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
+ u32 component, const char *module, u32 line)
+{
+ struct acpi_memory_list *mem_list;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ut_remove_allocation);
+
+ if (acpi_gbl_disable_mem_tracking) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ mem_list = acpi_gbl_global_list;
+ if (NULL == mem_list->list_head) {
+
+ /* No allocations! */
+
+ ACPI_ERROR((module, line,
+ "Empty allocation list, nothing to free!"));
+
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Unlink */
+
+ if (allocation->previous) {
+ (allocation->previous)->next = allocation->next;
+ } else {
+ mem_list->list_head = allocation->next;
+ }
+
+ if (allocation->next) {
+ (allocation->next)->previous = allocation->previous;
+ }
+
+ /* Mark the segment as deleted */
+
+ ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
+ allocation->size));
+
+ status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_dump_allocation_info
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Print some info about the outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocation_info(void)
+{
+/*
+ struct acpi_memory_list *mem_list;
+*/
+
+ ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
+
+/*
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Current allocations",
+ mem_list->current_count,
+ ROUND_UP_TO_1K (mem_list->current_size)));
+
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
+ mem_list->max_concurrent_count,
+ ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
+
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
+ running_object_count,
+ ROUND_UP_TO_1K (running_object_size)));
+
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
+ running_alloc_count,
+ ROUND_UP_TO_1K (running_alloc_size)));
+
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Current Nodes",
+ acpi_gbl_current_node_count,
+ ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
+
+ ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+ ("%30s: %4d (%3d Kb)\n", "Max Nodes",
+ acpi_gbl_max_concurrent_node_count,
+ ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
+ sizeof (struct acpi_namespace_node)))));
+*/
+ return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_dump_allocations
+ *
+ * PARAMETERS: component - Component(s) to dump info for.
+ * module - Module to dump info for. NULL means all.
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Print a list of all outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocations(u32 component, const char *module)
+{
+ struct acpi_debug_mem_block *element;
+ union acpi_descriptor *descriptor;
+ u32 num_outstanding = 0;
+ u8 descriptor_type;
+
+ ACPI_FUNCTION_TRACE(ut_dump_allocations);
+
+ if (acpi_gbl_disable_mem_tracking) {
+ return_VOID;
+ }
+
+ /*
+ * Walk the allocation list.
+ */
+ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
+ return_VOID;
+ }
+
+ element = acpi_gbl_global_list->list_head;
+ while (element) {
+ if ((element->component & component) &&
+ ((module == NULL)
+ || (0 == ACPI_STRCMP(module, element->module)))) {
+ descriptor =
+ ACPI_CAST_PTR(union acpi_descriptor,
+ &element->user_space);
+
+ if (element->size <
+ sizeof(struct acpi_common_descriptor)) {
+ acpi_os_printf("%p Length 0x%04X %9.9s-%u "
+ "[Not a Descriptor - too small]\n",
+ descriptor, element->size,
+ element->module, element->line);
+ } else {
+ /* Ignore allocated objects that are in a cache */
+
+ if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
+ ACPI_DESC_TYPE_CACHED) {
+ acpi_os_printf
+ ("%p Length 0x%04X %9.9s-%u [%s] ",
+ descriptor, element->size,
+ element->module, element->line,
+ acpi_ut_get_descriptor_name
+ (descriptor));
+
+ /* Validate the descriptor type using Type field and length */
+
+ descriptor_type = 0; /* Not a valid descriptor type */
+
+ switch (ACPI_GET_DESCRIPTOR_TYPE
+ (descriptor)) {
+ case ACPI_DESC_TYPE_OPERAND:
+ if (element->size ==
+ sizeof(union
+ acpi_operand_object))
+ {
+ descriptor_type =
+ ACPI_DESC_TYPE_OPERAND;
+ }
+ break;
+
+ case ACPI_DESC_TYPE_PARSER:
+ if (element->size ==
+ sizeof(union
+ acpi_parse_object)) {
+ descriptor_type =
+ ACPI_DESC_TYPE_PARSER;
+ }
+ break;
+
+ case ACPI_DESC_TYPE_NAMED:
+ if (element->size ==
+ sizeof(struct
+ acpi_namespace_node))
+ {
+ descriptor_type =
+ ACPI_DESC_TYPE_NAMED;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Display additional info for the major descriptor types */
+
+ switch (descriptor_type) {
+ case ACPI_DESC_TYPE_OPERAND:
+ acpi_os_printf
+ ("%12.12s RefCount 0x%04X\n",
+ acpi_ut_get_type_name
+ (descriptor->object.common.
+ type),
+ descriptor->object.common.
+ reference_count);
+ break;
+
+ case ACPI_DESC_TYPE_PARSER:
+ acpi_os_printf
+ ("AmlOpcode 0x%04hX\n",
+ descriptor->op.asl.
+ aml_opcode);
+ break;
+
+ case ACPI_DESC_TYPE_NAMED:
+ acpi_os_printf("%4.4s\n",
+ acpi_ut_get_node_name
+ (&descriptor->
+ node));
+ break;
+
+ default:
+ acpi_os_printf("\n");
+ break;
+ }
+ }
+ }
+
+ num_outstanding++;
+ }
+
+ element = element->next;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+
+ /* Print summary */
+
+ if (!num_outstanding) {
+ ACPI_INFO((AE_INFO, "No outstanding allocations"));
+ } else {
+ ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
+ num_outstanding, num_outstanding));
+ }
+
+ return_VOID;
+}
+
+#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index b09632b4f5b3..390db0ca5e2e 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -147,7 +147,7 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status)
* RETURN: status - the status of the call
*
* DESCRIPTION: This function is called to get information about the current
- * state of the ACPI subsystem. It will return system information
+ * state of the ACPI subsystem. It will return system information
* in the out_buffer.
*
* If the function fails an appropriate status will be returned
@@ -238,7 +238,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
}
acpi_gbl_init_handler = handler;
- return AE_OK;
+ return (AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
@@ -263,6 +263,7 @@ acpi_status acpi_purge_cached_objects(void)
(void)acpi_os_purge_cache(acpi_gbl_operand_cache);
(void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);
(void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
+
return_ACPI_STATUS(AE_OK);
}
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
index 6d63cc39b9ae..d4d3826140d8 100644
--- a/drivers/acpi/acpica/utxferror.c
+++ b/drivers/acpi/acpica/utxferror.c
@@ -408,7 +408,7 @@ acpi_ut_namespace_error(const char *module_name,
ACPI_MOVE_32_TO_32(&bad_name,
ACPI_CAST_PTR(u32, internal_name));
- acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
+ acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 1599566ed1fe..7ae2750bb457 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -901,7 +901,7 @@ static unsigned long ghes_esource_prealloc_size(
return prealloc_size;
}
-static int __devinit ghes_probe(struct platform_device *ghes_dev)
+static int ghes_probe(struct platform_device *ghes_dev)
{
struct acpi_hest_generic *generic;
struct ghes *ghes = NULL;
@@ -994,7 +994,7 @@ err:
return rc;
}
-static int __devexit ghes_remove(struct platform_device *ghes_dev)
+static int ghes_remove(struct platform_device *ghes_dev)
{
struct ghes *ghes;
struct acpi_hest_generic *generic;
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 45e3e1759fb8..7efaeaa53b88 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -34,6 +34,7 @@
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/suspend.h>
+#include <asm/unaligned.h>
#ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h>
@@ -95,6 +96,18 @@ enum {
ACPI_BATTERY_ALARM_PRESENT,
ACPI_BATTERY_XINFO_PRESENT,
ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
+ /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
+ switches between mWh and mAh depending on whether the system
+ is running on battery or not. When mAh is the unit, most
+ reported values are incorrect and need to be adjusted by
+ 10000/design_voltage. Verified on x201, t410, t410s, and x220.
+ Pre-2010 and 2012 models appear to always report in mWh and
+ are thus unaffected (tested with t42, t61, t500, x200, x300,
+ and x230). Also, in mid-2012 Lenovo issued a BIOS update for
+ the 2011 models that fixes the issue (tested on x220 with a
+ post-1.29 BIOS), but as of Nov. 2012, no such update is
+ available for the 2010 models. */
+ ACPI_BATTERY_QUIRK_THINKPAD_MAH,
};
struct acpi_battery {
@@ -438,6 +451,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
+ if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+ battery->power_unit && battery->design_voltage) {
+ battery->design_capacity = battery->design_capacity *
+ 10000 / battery->design_voltage;
+ battery->full_charge_capacity = battery->full_charge_capacity *
+ 10000 / battery->design_voltage;
+ battery->design_capacity_warning =
+ battery->design_capacity_warning *
+ 10000 / battery->design_voltage;
+ /* Curiously, design_capacity_low, unlike the rest of them,
+ is correct. */
+ /* capacity_granularity_* equal 1 on the systems tested, so
+ it's impossible to tell if they would need an adjustment
+ or not if their values were higher. */
+ }
return result;
}
@@ -486,6 +514,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
&& battery->capacity_now >= 0 && battery->capacity_now <= 100)
battery->capacity_now = (battery->capacity_now *
battery->full_charge_capacity) / 100;
+ if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+ battery->power_unit && battery->design_voltage) {
+ battery->capacity_now = battery->capacity_now *
+ 10000 / battery->design_voltage;
+ }
return result;
}
@@ -595,6 +628,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
mutex_unlock(&battery->sysfs_lock);
}
+static void find_battery(const struct dmi_header *dm, void *private)
+{
+ struct acpi_battery *battery = (struct acpi_battery *)private;
+ /* Note: the hardcoded offsets below have been extracted from
+ the source code of dmidecode. */
+ if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
+ const u8 *dmi_data = (const u8 *)(dm + 1);
+ int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
+ if (dm->length >= 18)
+ dmi_capacity *= dmi_data[17];
+ if (battery->design_capacity * battery->design_voltage / 1000
+ != dmi_capacity &&
+ battery->design_capacity * 10 == dmi_capacity)
+ set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+ &battery->flags);
+ }
+}
+
/*
* According to the ACPI spec, some kinds of primary batteries can
* report percentage battery remaining capacity directly to OS.
@@ -620,6 +671,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
battery->capacity_now = (battery->capacity_now *
battery->full_charge_capacity) / 100;
}
+
+ if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
+ return ;
+
+ if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
+ const char *s;
+ s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+ if (s && !strnicmp(s, "ThinkPad", 8)) {
+ dmi_walk(find_battery, battery);
+ if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+ &battery->flags) &&
+ battery->design_voltage) {
+ battery->design_capacity =
+ battery->design_capacity *
+ 10000 / battery->design_voltage;
+ battery->full_charge_capacity =
+ battery->full_charge_capacity *
+ 10000 / battery->design_voltage;
+ battery->design_capacity_warning =
+ battery->design_capacity_warning *
+ 10000 / battery->design_voltage;
+ battery->capacity_now = battery->capacity_now *
+ 10000 / battery->design_voltage;
+ }
+ }
+ }
}
static int acpi_battery_update(struct acpi_battery *battery)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d59175efc428..1f0d457ecbcf 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -257,7 +257,15 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
}
-static int __acpi_bus_set_power(struct acpi_device *device, int state)
+/**
+ * acpi_device_set_power - Set power state of an ACPI device.
+ * @device: Device to set the power state of.
+ * @state: New power state to set.
+ *
+ * Callers must ensure that the device is power manageable before using this
+ * function.
+ */
+int acpi_device_set_power(struct acpi_device *device, int state)
{
int result = 0;
acpi_status status = AE_OK;
@@ -298,6 +306,12 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
* a lower-powered state.
*/
if (state < device->power.state) {
+ if (device->power.state >= ACPI_STATE_D3_HOT &&
+ state != ACPI_STATE_D0) {
+ printk(KERN_WARNING PREFIX
+ "Cannot transition to non-D0 state from D3\n");
+ return -ENODEV;
+ }
if (device->power.flags.power_resources) {
result = acpi_power_transition(device, state);
if (result)
@@ -341,6 +355,7 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
return result;
}
+EXPORT_SYMBOL(acpi_device_set_power);
int acpi_bus_set_power(acpi_handle handle, int state)
@@ -359,7 +374,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
return -ENODEV;
}
- return __acpi_bus_set_power(device, state);
+ return acpi_device_set_power(device, state);
}
EXPORT_SYMBOL(acpi_bus_set_power);
@@ -402,7 +417,7 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
if (result)
return result;
- result = __acpi_bus_set_power(device, state);
+ result = acpi_device_set_power(device, state);
if (!result && state_p)
*state_p = state;
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 1f9f7d7d7bc5..811910b50b75 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -92,17 +92,24 @@ static int is_device_present(acpi_handle handle)
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}
+static bool is_container_device(const char *hid)
+{
+ const struct acpi_device_id *container_id;
+
+ for (container_id = container_device_ids;
+ container_id->id[0]; container_id++) {
+ if (!strcmp((char *)container_id->id, hid))
+ return true;
+ }
+
+ return false;
+}
+
/*******************************************************************/
static int acpi_container_add(struct acpi_device *device)
{
struct acpi_container *container;
-
- if (!device) {
- printk(KERN_ERR PREFIX "device is NULL\n");
- return -EINVAL;
- }
-
container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
if (!container)
return -ENOMEM;
@@ -164,7 +171,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
case ACPI_NOTIFY_BUS_CHECK:
/* Fall through */
case ACPI_NOTIFY_DEVICE_CHECK:
- printk(KERN_WARNING "Container driver received %s event\n",
+ pr_debug("Container driver received %s event\n",
(type == ACPI_NOTIFY_BUS_CHECK) ?
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
@@ -185,7 +192,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
result = container_device_add(&device, handle);
if (result) {
- printk(KERN_WARNING "Failed to add container\n");
+ acpi_handle_warn(handle, "Failed to add container\n");
break;
}
@@ -232,10 +239,8 @@ container_walk_namespace_cb(acpi_handle handle,
goto end;
}
- if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
- strcmp(hid, "PNP0A06")) {
+ if (!is_container_device(hid))
goto end;
- }
switch (*action) {
case INSTALL_NOTIFY_HANDLER:
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
new file mode 100644
index 000000000000..f09dc987cf17
--- /dev/null
+++ b/drivers/acpi/device_pm.c
@@ -0,0 +1,668 @@
+/*
+ * drivers/acpi/device_pm.c - ACPI device power management routines.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/pm_qos.h>
+#include <linux/pm_runtime.h>
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+static DEFINE_MUTEX(acpi_pm_notifier_lock);
+
+/**
+ * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
+ * @adev: ACPI device to add the notifier for.
+ * @context: Context information to pass to the notifier routine.
+ *
+ * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
+ * PM wakeup events. For example, wakeup events may be generated for bridges
+ * if one of the devices below the bridge is signaling wakeup, even if the
+ * bridge itself doesn't have a wakeup GPE associated with it.
+ */
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler, void *context)
+{
+ acpi_status status = AE_ALREADY_EXISTS;
+
+ mutex_lock(&acpi_pm_notifier_lock);
+
+ if (adev->wakeup.flags.notifier_present)
+ goto out;
+
+ status = acpi_install_notify_handler(adev->handle,
+ ACPI_SYSTEM_NOTIFY,
+ handler, context);
+ if (ACPI_FAILURE(status))
+ goto out;
+
+ adev->wakeup.flags.notifier_present = true;
+
+ out:
+ mutex_unlock(&acpi_pm_notifier_lock);
+ return status;
+}
+
+/**
+ * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
+ * @adev: ACPI device to remove the notifier from.
+ */
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler)
+{
+ acpi_status status = AE_BAD_PARAMETER;
+
+ mutex_lock(&acpi_pm_notifier_lock);
+
+ if (!adev->wakeup.flags.notifier_present)
+ goto out;
+
+ status = acpi_remove_notify_handler(adev->handle,
+ ACPI_SYSTEM_NOTIFY,
+ handler);
+ if (ACPI_FAILURE(status))
+ goto out;
+
+ adev->wakeup.flags.notifier_present = false;
+
+ out:
+ mutex_unlock(&acpi_pm_notifier_lock);
+ return status;
+}
+
+/**
+ * acpi_device_power_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @adev: ACPI device node corresponding to @dev.
+ * @target_state: System state to match the resultant device state.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * Return value: Preferred power state of the device on success, -ENODEV
+ * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
+ *
+ * Find the lowest power (highest number) ACPI device power state that the
+ * device can be in while the system is in the state represented by
+ * @target_state. If @d_min_p is set, the highest power (lowest number) device
+ * power state that @dev can be in for the given system sleep state is stored
+ * at the location pointed to by it.
+ *
+ * Callers must ensure that @dev and @adev are valid pointers and that @adev
+ * actually corresponds to @dev before using this function.
+ */
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+ u32 target_state, int d_max_in, int *d_min_p)
+{
+ char acpi_method[] = "_SxD";
+ unsigned long long d_min, d_max;
+ bool wakeup = false;
+
+ if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
+ return -EINVAL;
+
+ if (d_max_in > ACPI_STATE_D3_HOT) {
+ enum pm_qos_flags_status stat;
+
+ stat = dev_pm_qos_flags(dev, PM_QOS_FLAG_NO_POWER_OFF);
+ if (stat == PM_QOS_FLAGS_ALL)
+ d_max_in = ACPI_STATE_D3_HOT;
+ }
+
+ acpi_method[2] = '0' + target_state;
+ /*
+ * If the sleep state is S0, the lowest limit from ACPI is D3,
+ * but if the device has _S0W, we will use the value from _S0W
+ * as the lowest limit from ACPI. Finally, we will constrain
+ * the lowest limit with the specified one.
+ */
+ d_min = ACPI_STATE_D0;
+ d_max = ACPI_STATE_D3;
+
+ /*
+ * If present, _SxD methods return the minimum D-state (highest power
+ * state) we can use for the corresponding S-states. Otherwise, the
+ * minimum D-state is D0 (ACPI 3.x).
+ *
+ * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
+ * provided -- that's our fault recovery, we ignore retval.
+ */
+ if (target_state > ACPI_STATE_S0) {
+ acpi_evaluate_integer(adev->handle, acpi_method, NULL, &d_min);
+ wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
+ && adev->wakeup.sleep_state >= target_state;
+ } else if (dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) !=
+ PM_QOS_FLAGS_NONE) {
+ wakeup = adev->wakeup.flags.valid;
+ }
+
+ /*
+ * If _PRW says we can wake up the system from the target sleep state,
+ * the D-state returned by _SxD is sufficient for that (we assume a
+ * wakeup-aware driver if wake is set). Still, if _SxW exists
+ * (ACPI 3.x), it should return the maximum (lowest power) D-state that
+ * can wake the system. _S0W may be valid, too.
+ */
+ if (wakeup) {
+ acpi_status status;
+
+ acpi_method[3] = 'W';
+ status = acpi_evaluate_integer(adev->handle, acpi_method, NULL,
+ &d_max);
+ if (ACPI_FAILURE(status)) {
+ if (target_state != ACPI_STATE_S0 ||
+ status != AE_NOT_FOUND)
+ d_max = d_min;
+ } else if (d_max < d_min) {
+ /* Warn the user of the broken DSDT */
+ printk(KERN_WARNING "ACPI: Wrong value from %s\n",
+ acpi_method);
+ /* Sanitize it */
+ d_min = d_max;
+ }
+ }
+
+ if (d_max_in < d_min)
+ return -EINVAL;
+ if (d_min_p)
+ *d_min_p = d_min;
+ /* constrain d_max with specified lowest limit (max number) */
+ if (d_max > d_max_in) {
+ for (d_max = d_max_in; d_max > d_min; d_max--) {
+ if (adev->power.states[d_max].flags.valid)
+ break;
+ }
+ }
+ return d_max;
+}
+EXPORT_SYMBOL_GPL(acpi_device_power_state);
+
+/**
+ * acpi_pm_device_sleep_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * Return value: Preferred power state of the device on success, -ENODEV
+ * (if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
+ *
+ * The caller must ensure that @dev is valid before using this function.
+ */
+int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
+{
+ acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+ struct acpi_device *adev;
+
+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+ dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+ return -ENODEV;
+ }
+
+ return acpi_device_power_state(dev, adev, acpi_target_system_state(),
+ d_max_in, d_min_p);
+}
+EXPORT_SYMBOL(acpi_pm_device_sleep_state);
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_wakeup_device - Wakeup notification handler for ACPI devices.
+ * @handle: ACPI handle of the device the notification is for.
+ * @event: Type of the signaled event.
+ * @context: Device corresponding to @handle.
+ */
+static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
+{
+ struct device *dev = context;
+
+ if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) {
+ pm_wakeup_event(dev, 0);
+ pm_runtime_resume(dev);
+ }
+}
+
+/**
+ * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device.
+ * @adev: ACPI device to enable/disable the remote wakeup for.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ *
+ * Enable/disable the GPE associated with @adev so that it can generate
+ * wakeup signals for the device in response to external (remote) events and
+ * enable/disable device wakeup power.
+ *
+ * Callers must ensure that @adev is a valid ACPI device node before executing
+ * this function.
+ */
+int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
+{
+ struct acpi_device_wakeup *wakeup = &adev->wakeup;
+
+ if (enable) {
+ acpi_status res;
+ int error;
+
+ error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
+ if (error)
+ return error;
+
+ res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+ if (ACPI_FAILURE(res)) {
+ acpi_disable_wakeup_device_power(adev);
+ return -EIO;
+ }
+ } else {
+ acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+ acpi_disable_wakeup_device_power(adev);
+ }
+ return 0;
+}
+
+/**
+ * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
+ * @dev: Device to enable/disable the platform to wake up.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ */
+int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
+{
+ struct acpi_device *adev;
+ acpi_handle handle;
+
+ if (!device_run_wake(phys_dev))
+ return -EINVAL;
+
+ handle = DEVICE_ACPI_HANDLE(phys_dev);
+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+ dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ return __acpi_device_run_wake(adev, enable);
+}
+EXPORT_SYMBOL(acpi_pm_device_run_wake);
+#else
+static inline void acpi_wakeup_device(acpi_handle handle, u32 event,
+ void *context) {}
+#endif /* CONFIG_PM_RUNTIME */
+
+ #ifdef CONFIG_PM_SLEEP
+/**
+ * __acpi_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system.
+ * @target_state: System state the device is supposed to wake up from.
+ * @enable: Whether to enable or disable @dev to wake up the system.
+ */
+int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
+ bool enable)
+{
+ return enable ?
+ acpi_enable_wakeup_device_power(adev, target_state) :
+ acpi_disable_wakeup_device_power(adev);
+}
+
+/**
+ * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system from sleep states.
+ * @enable: Whether to enable or disable @dev to wake up the system.
+ */
+int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
+{
+ acpi_handle handle;
+ struct acpi_device *adev;
+ int error;
+
+ if (!device_can_wakeup(dev))
+ return -EINVAL;
+
+ handle = DEVICE_ACPI_HANDLE(dev);
+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+ dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+ return -ENODEV;
+ }
+
+ error = __acpi_device_sleep_wake(adev, acpi_target_system_state(),
+ enable);
+ if (!error)
+ dev_info(dev, "System wakeup %s by ACPI\n",
+ enable ? "enabled" : "disabled");
+
+ return error;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
+ * @dev: Device to get the ACPI node for.
+ */
+static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+{
+ acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+ struct acpi_device *adev;
+
+ return handle && ACPI_SUCCESS(acpi_bus_get_device(handle, &adev)) ?
+ adev : NULL;
+}
+
+/**
+ * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
+ * @dev: Device to put into a low-power state.
+ * @adev: ACPI device node corresponding to @dev.
+ * @system_state: System state to choose the device state for.
+ */
+static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev,
+ u32 system_state)
+{
+ int power_state;
+
+ if (!acpi_device_power_manageable(adev))
+ return 0;
+
+ power_state = acpi_device_power_state(dev, adev, system_state,
+ ACPI_STATE_D3, NULL);
+ if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3)
+ return -EIO;
+
+ return acpi_device_set_power(adev, power_state);
+}
+
+/**
+ * acpi_dev_pm_full_power - Put ACPI device into the full-power state.
+ * @adev: ACPI device node to put into the full-power state.
+ */
+static int acpi_dev_pm_full_power(struct acpi_device *adev)
+{
+ return acpi_device_power_manageable(adev) ?
+ acpi_device_set_power(adev, ACPI_STATE_D0) : 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a runtime low-power state using the standard ACPI
+ * mechanism. Set up remote wakeup if desired, choose the state to put the
+ * device into (this checks if remote wakeup is expected to work too), and set
+ * the power state of the device.
+ */
+int acpi_dev_runtime_suspend(struct device *dev)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+ bool remote_wakeup;
+ int error;
+
+ if (!adev)
+ return 0;
+
+ remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
+ PM_QOS_FLAGS_NONE;
+ error = __acpi_device_run_wake(adev, remote_wakeup);
+ if (remote_wakeup && error)
+ return -EAGAIN;
+
+ error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+ if (error)
+ __acpi_device_run_wake(adev, false);
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend);
+
+/**
+ * acpi_dev_runtime_resume - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism at run time. Set the power state of the device to ACPI D0 and
+ * disable remote wakeup.
+ */
+int acpi_dev_runtime_resume(struct device *dev)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+ int error;
+
+ if (!adev)
+ return 0;
+
+ error = acpi_dev_pm_full_power(adev);
+ __acpi_device_run_wake(adev, false);
+ return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
+
+/**
+ * acpi_subsys_runtime_suspend - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic runtime suspend procedure for @dev and use ACPI to put
+ * it into a runtime low-power state.
+ */
+int acpi_subsys_runtime_suspend(struct device *dev)
+{
+ int ret = pm_generic_runtime_suspend(dev);
+ return ret ? ret : acpi_dev_runtime_suspend(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend);
+
+/**
+ * acpi_subsys_runtime_resume - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic runtime resume procedure for it.
+ */
+int acpi_subsys_runtime_resume(struct device *dev)
+{
+ int ret = acpi_dev_runtime_resume(dev);
+ return ret ? ret : pm_generic_runtime_resume(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume);
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * acpi_dev_suspend_late - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a low-power state during system transition to a
+ * sleep state using the standard ACPI mechanism. Set up system wakeup if
+ * desired, choose the state to put the device into (this checks if system
+ * wakeup is expected to work too), and set the power state of the device.
+ */
+int acpi_dev_suspend_late(struct device *dev)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+ u32 target_state;
+ bool wakeup;
+ int error;
+
+ if (!adev)
+ return 0;
+
+ target_state = acpi_target_system_state();
+ wakeup = device_may_wakeup(dev);
+ error = __acpi_device_sleep_wake(adev, target_state, wakeup);
+ if (wakeup && error)
+ return error;
+
+ error = acpi_dev_pm_low_power(dev, adev, target_state);
+ if (error)
+ __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_suspend_late);
+
+/**
+ * acpi_dev_resume_early - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism during system transition to the working state. Set the power
+ * state of the device to ACPI D0 and disable remote wakeup.
+ */
+int acpi_dev_resume_early(struct device *dev)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+ int error;
+
+ if (!adev)
+ return 0;
+
+ error = acpi_dev_pm_full_power(adev);
+ __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+ return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
+
+/**
+ * acpi_subsys_prepare - Prepare device for system transition to a sleep state.
+ * @dev: Device to prepare.
+ */
+int acpi_subsys_prepare(struct device *dev)
+{
+ /*
+ * Follow PCI and resume devices suspended at run time before running
+ * their system suspend callbacks.
+ */
+ pm_runtime_resume(dev);
+ return pm_generic_prepare(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
+
+/**
+ * acpi_subsys_suspend_late - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic late suspend procedure for @dev and use ACPI to put
+ * it into a low-power state during system transition into a sleep state.
+ */
+int acpi_subsys_suspend_late(struct device *dev)
+{
+ int ret = pm_generic_suspend_late(dev);
+ return ret ? ret : acpi_dev_suspend_late(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late);
+
+/**
+ * acpi_subsys_resume_early - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic early resume procedure for it during system transition into the
+ * working state.
+ */
+int acpi_subsys_resume_early(struct device *dev)
+{
+ int ret = acpi_dev_resume_early(dev);
+ return ret ? ret : pm_generic_resume_early(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);
+#endif /* CONFIG_PM_SLEEP */
+
+static struct dev_pm_domain acpi_general_pm_domain = {
+ .ops = {
+#ifdef CONFIG_PM_RUNTIME
+ .runtime_suspend = acpi_subsys_runtime_suspend,
+ .runtime_resume = acpi_subsys_runtime_resume,
+ .runtime_idle = pm_generic_runtime_idle,
+#endif
+#ifdef CONFIG_PM_SLEEP
+ .prepare = acpi_subsys_prepare,
+ .suspend_late = acpi_subsys_suspend_late,
+ .resume_early = acpi_subsys_resume_early,
+ .poweroff_late = acpi_subsys_suspend_late,
+ .restore_early = acpi_subsys_resume_early,
+#endif
+ },
+};
+
+/**
+ * acpi_dev_pm_attach - Prepare device for ACPI power management.
+ * @dev: Device to prepare.
+ * @power_on: Whether or not to power on the device.
+ *
+ * If @dev has a valid ACPI handle that has a valid struct acpi_device object
+ * attached to it, install a wakeup notification handler for the device and
+ * add it to the general ACPI PM domain. If @power_on is set, the device will
+ * be put into the ACPI D0 state before the function returns.
+ *
+ * This assumes that the @dev's bus type uses generic power management callbacks
+ * (or doesn't use any power management callbacks at all).
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+ if (!adev)
+ return -ENODEV;
+
+ if (dev->pm_domain)
+ return -EEXIST;
+
+ acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
+ dev->pm_domain = &acpi_general_pm_domain;
+ if (power_on) {
+ acpi_dev_pm_full_power(adev);
+ __acpi_device_run_wake(adev, false);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
+
+/**
+ * acpi_dev_pm_detach - Remove ACPI power management from the device.
+ * @dev: Device to take care of.
+ * @power_off: Whether or not to try to remove power from the device.
+ *
+ * Remove the device from the general ACPI PM domain and remove its wakeup
+ * notifier. If @power_off is set, additionally remove power from the device if
+ * possible.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+void acpi_dev_pm_detach(struct device *dev, bool power_off)
+{
+ struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+ if (adev && dev->pm_domain == &acpi_general_pm_domain) {
+ dev->pm_domain = NULL;
+ acpi_remove_pm_notifier(adev, acpi_wakeup_device);
+ if (power_off) {
+ /*
+ * If the device's PM QoS resume latency limit or flags
+ * have been exposed to user space, they have to be
+ * hidden at this point, so that they don't affect the
+ * choice of the low-power state to put the device into.
+ */
+ dev_pm_qos_hide_latency_limit(dev);
+ dev_pm_qos_hide_flags(dev);
+ __acpi_device_run_wake(adev, false);
+ acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 88eb14304667..f32bd47b35e0 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/stddef.h>
+#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -460,12 +461,8 @@ static void handle_dock(struct dock_station *ds, int dock)
struct acpi_object_list arg_list;
union acpi_object arg;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
-
- printk(KERN_INFO PREFIX "%s - %s\n",
- (char *)name_buffer.pointer, dock ? "docking" : "undocking");
+ acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
/* _DCK method has one argument */
arg_list.count = 1;
@@ -474,11 +471,10 @@ static void handle_dock(struct dock_station *ds, int dock)
arg.integer.value = dock;
status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
- ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
- " _DCK\n", (char *)name_buffer.pointer));
+ acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
+ status);
kfree(buffer.pointer);
- kfree(name_buffer.pointer);
}
static inline void dock(struct dock_station *ds)
@@ -525,9 +521,11 @@ static void dock_lock(struct dock_station *ds, int lock)
status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
if (lock)
- printk(KERN_WARNING PREFIX "Locking device failed\n");
+ acpi_handle_warn(ds->handle,
+ "Locking device failed (0x%x)\n", status);
else
- printk(KERN_WARNING PREFIX "Unlocking device failed\n");
+ acpi_handle_warn(ds->handle,
+ "Unlocking device failed (0x%x)\n", status);
}
}
@@ -667,7 +665,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
dock_lock(ds, 0);
eject_dock(ds);
if (dock_present(ds)) {
- printk(KERN_ERR PREFIX "Unable to undock!\n");
+ acpi_handle_err(ds->handle, "Unable to undock!\n");
return -EBUSY;
}
complete_undock(ds);
@@ -715,7 +713,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
begin_dock(ds);
dock(ds);
if (!dock_present(ds)) {
- printk(KERN_ERR PREFIX "Unable to dock!\n");
+ acpi_handle_err(handle, "Unable to dock!\n");
complete_dock(ds);
break;
}
@@ -743,7 +741,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
dock_event(ds, event, UNDOCK_EVENT);
break;
default:
- printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
+ acpi_handle_err(handle, "Unknown dock event %d\n", event);
}
}
@@ -987,7 +985,7 @@ err_rmgroup:
sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
err_unregister:
platform_device_unregister(dd);
- printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
+ acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
return ret;
}
@@ -1016,51 +1014,39 @@ static int dock_remove(struct dock_station *ds)
}
/**
- * find_dock - look for a dock station
+ * find_dock_and_bay - look for dock stations and bays
* @handle: acpi handle of a device
* @lvl: unused
- * @context: counter of dock stations found
+ * @context: unused
* @rv: unused
*
- * This is called by acpi_walk_namespace to look for dock stations.
+ * This is called by acpi_walk_namespace to look for dock stations and bays.
*/
static __init acpi_status
-find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
+find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
{
- if (is_dock(handle))
+ if (is_dock(handle) || is_ejectable_bay(handle))
dock_add(handle);
return AE_OK;
}
-static __init acpi_status
-find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- /* If bay is a dock, it's already handled */
- if (is_ejectable_bay(handle) && !is_dock(handle))
- dock_add(handle);
- return AE_OK;
-}
-
static int __init dock_init(void)
{
if (acpi_disabled)
return 0;
- /* look for a dock station */
+ /* look for dock stations and bays */
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_dock, NULL, NULL, NULL);
+ ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
- /* look for bay */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_bay, NULL, NULL, NULL);
if (!dock_station_count) {
- printk(KERN_INFO PREFIX "No dock devices found.\n");
+ pr_info(PREFIX "No dock devices found.\n");
return 0;
}
register_acpi_bus_notifier(&dock_acpi_notifier);
- printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
+ pr_info(PREFIX "%s: %d docks/bays found\n",
ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
return 0;
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a51df9681319..354007d490d1 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -158,10 +158,10 @@ static int ec_transaction_done(struct acpi_ec *ec)
{
unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&ec->curr_lock, flags);
+ spin_lock_irqsave(&ec->lock, flags);
if (!ec->curr || ec->curr->done)
ret = 1;
- spin_unlock_irqrestore(&ec->curr_lock, flags);
+ spin_unlock_irqrestore(&ec->lock, flags);
return ret;
}
@@ -175,32 +175,38 @@ static void start_transaction(struct acpi_ec *ec)
static void advance_transaction(struct acpi_ec *ec, u8 status)
{
unsigned long flags;
- spin_lock_irqsave(&ec->curr_lock, flags);
- if (!ec->curr)
+ struct transaction *t = ec->curr;
+
+ spin_lock_irqsave(&ec->lock, flags);
+ if (!t)
goto unlock;
- if (ec->curr->wlen > ec->curr->wi) {
+ if (t->wlen > t->wi) {
if ((status & ACPI_EC_FLAG_IBF) == 0)
acpi_ec_write_data(ec,
- ec->curr->wdata[ec->curr->wi++]);
+ t->wdata[t->wi++]);
else
goto err;
- } else if (ec->curr->rlen > ec->curr->ri) {
+ } else if (t->rlen > t->ri) {
if ((status & ACPI_EC_FLAG_OBF) == 1) {
- ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec);
- if (ec->curr->rlen == ec->curr->ri)
- ec->curr->done = true;
+ t->rdata[t->ri++] = acpi_ec_read_data(ec);
+ if (t->rlen == t->ri)
+ t->done = true;
} else
goto err;
- } else if (ec->curr->wlen == ec->curr->wi &&
+ } else if (t->wlen == t->wi &&
(status & ACPI_EC_FLAG_IBF) == 0)
- ec->curr->done = true;
+ t->done = true;
goto unlock;
err:
- /* false interrupt, state didn't change */
- if (in_interrupt())
- ++ec->curr->irq_count;
+ /*
+ * If SCI bit is set, then don't think it's a false IRQ
+ * otherwise will take a not handled IRQ as a false one.
+ */
+ if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI))
+ ++t->irq_count;
+
unlock:
- spin_unlock_irqrestore(&ec->curr_lock, flags);
+ spin_unlock_irqrestore(&ec->lock, flags);
}
static int acpi_ec_sync_query(struct acpi_ec *ec);
@@ -238,9 +244,9 @@ static int ec_poll(struct acpi_ec *ec)
if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
break;
pr_debug(PREFIX "controller reset, restart transaction\n");
- spin_lock_irqsave(&ec->curr_lock, flags);
+ spin_lock_irqsave(&ec->lock, flags);
start_transaction(ec);
- spin_unlock_irqrestore(&ec->curr_lock, flags);
+ spin_unlock_irqrestore(&ec->lock, flags);
}
return -ETIME;
}
@@ -253,17 +259,17 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
if (EC_FLAGS_MSI)
udelay(ACPI_EC_MSI_UDELAY);
/* start transaction */
- spin_lock_irqsave(&ec->curr_lock, tmp);
+ spin_lock_irqsave(&ec->lock, tmp);
/* following two actions should be kept atomic */
ec->curr = t;
start_transaction(ec);
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
- spin_unlock_irqrestore(&ec->curr_lock, tmp);
+ spin_unlock_irqrestore(&ec->lock, tmp);
ret = ec_poll(ec);
- spin_lock_irqsave(&ec->curr_lock, tmp);
+ spin_lock_irqsave(&ec->lock, tmp);
ec->curr = NULL;
- spin_unlock_irqrestore(&ec->curr_lock, tmp);
+ spin_unlock_irqrestore(&ec->lock, tmp);
return ret;
}
@@ -292,7 +298,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
return -EINVAL;
if (t->rdata)
memset(t->rdata, 0, t->rlen);
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
status = -EINVAL;
goto unlock;
@@ -310,7 +316,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
status = -ETIME;
goto end;
}
- pr_debug(PREFIX "transaction start\n");
+ pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+ t->command, t->wdata ? t->wdata[0] : 0);
/* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
/* It has to be disabled, so that it doesn't trigger. */
@@ -326,8 +333,9 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
/* It is safe to enable the GPE outside of the transaction. */
acpi_enable_gpe(NULL, ec->gpe);
} else if (t->irq_count > ec_storm_threshold) {
- pr_info(PREFIX "GPE storm detected, "
- "transactions will use polling mode\n");
+ pr_info(PREFIX "GPE storm detected(%d GPEs), "
+ "transactions will use polling mode\n",
+ t->irq_count);
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
}
pr_debug(PREFIX "transaction end\n");
@@ -335,7 +343,7 @@ end:
if (ec->global_lock)
acpi_release_global_lock(glk);
unlock:
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
return status;
}
@@ -403,7 +411,7 @@ int ec_burst_disable(void)
EXPORT_SYMBOL(ec_burst_disable);
-int ec_read(u8 addr, u8 * val)
+int ec_read(u8 addr, u8 *val)
{
int err;
u8 temp_data;
@@ -468,10 +476,10 @@ void acpi_ec_block_transactions(void)
if (!ec)
return;
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
/* Prevent transactions from being carried out */
set_bit(EC_FLAGS_BLOCKED, &ec->flags);
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
}
void acpi_ec_unblock_transactions(void)
@@ -481,10 +489,10 @@ void acpi_ec_unblock_transactions(void)
if (!ec)
return;
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
/* Allow transactions to be carried out again */
clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
}
void acpi_ec_unblock_transactions_early(void)
@@ -536,9 +544,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
handler->handle = handle;
handler->func = func;
handler->data = data;
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
list_add(&handler->node, &ec->list);
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
return 0;
}
@@ -547,14 +555,14 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
{
struct acpi_ec_query_handler *handler, *tmp;
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
if (query_bit == handler->query_bit) {
list_del(&handler->node);
kfree(handler);
}
}
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
}
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
@@ -601,9 +609,9 @@ static void acpi_ec_gpe_query(void *ec_cxt)
struct acpi_ec *ec = ec_cxt;
if (!ec)
return;
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
acpi_ec_sync_query(ec);
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
}
static int ec_check_sci(struct acpi_ec *ec, u8 state)
@@ -622,10 +630,11 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
u32 gpe_number, void *data)
{
struct acpi_ec *ec = data;
+ u8 status = acpi_ec_read_status(ec);
- pr_debug(PREFIX "~~~> interrupt\n");
+ pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
- advance_transaction(ec, acpi_ec_read_status(ec));
+ advance_transaction(ec, status);
if (ec_transaction_done(ec) &&
(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
wake_up(&ec->wait);
@@ -691,10 +700,10 @@ static struct acpi_ec *make_acpi_ec(void)
if (!ec)
return NULL;
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
- mutex_init(&ec->lock);
+ mutex_init(&ec->mutex);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
- spin_lock_init(&ec->curr_lock);
+ spin_lock_init(&ec->lock);
return ec;
}
@@ -853,12 +862,12 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
ec = acpi_driver_data(device);
ec_remove_handlers(ec);
- mutex_lock(&ec->lock);
+ mutex_lock(&ec->mutex);
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
list_del(&handler->node);
kfree(handler);
}
- mutex_unlock(&ec->lock);
+ mutex_unlock(&ec->mutex);
release_region(ec->data_addr, 1);
release_region(ec->command_addr, 1);
device->driver_data = NULL;
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 08373086cd7e..01551840d236 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -130,46 +130,59 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
acpi_status status;
- struct acpi_device_physical_node *physical_node;
+ struct acpi_device_physical_node *physical_node, *pn;
char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
int retval = -EINVAL;
- if (dev->archdata.acpi_handle) {
- dev_warn(dev, "Drivers changed 'acpi_handle'\n");
- return -EINVAL;
+ if (ACPI_HANDLE(dev)) {
+ if (handle) {
+ dev_warn(dev, "ACPI handle is already set\n");
+ return -EINVAL;
+ } else {
+ handle = ACPI_HANDLE(dev);
+ }
}
+ if (!handle)
+ return -EINVAL;
get_device(dev);
status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_FAILURE(status))
goto err;
- physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
- GFP_KERNEL);
+ physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
if (!physical_node) {
retval = -ENOMEM;
goto err;
}
mutex_lock(&acpi_dev->physical_node_lock);
+
+ /* Sanity check. */
+ list_for_each_entry(pn, &acpi_dev->physical_node_list, node)
+ if (pn->dev == dev) {
+ dev_warn(dev, "Already associated with ACPI node\n");
+ goto err_free;
+ }
+
/* allocate physical node id according to physical_node_id_bitmap */
physical_node->node_id =
find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
ACPI_MAX_PHYSICAL_NODE);
if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
retval = -ENOSPC;
- mutex_unlock(&acpi_dev->physical_node_lock);
- kfree(physical_node);
- goto err;
+ goto err_free;
}
set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
physical_node->dev = dev;
list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
acpi_dev->physical_node_count++;
+
mutex_unlock(&acpi_dev->physical_node_lock);
- dev->archdata.acpi_handle = handle;
+ if (!ACPI_HANDLE(dev))
+ ACPI_HANDLE_SET(dev, acpi_dev->handle);
if (!physical_node->node_id)
strcpy(physical_node_name, PHYSICAL_NODE_STRING);
@@ -187,8 +200,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
return 0;
err:
+ ACPI_HANDLE_SET(dev, NULL);
put_device(dev);
return retval;
+
+ err_free:
+ mutex_unlock(&acpi_dev->physical_node_lock);
+ kfree(physical_node);
+ goto err;
}
static int acpi_unbind_one(struct device *dev)
@@ -198,11 +217,10 @@ static int acpi_unbind_one(struct device *dev)
acpi_status status;
struct list_head *node, *next;
- if (!dev->archdata.acpi_handle)
+ if (!ACPI_HANDLE(dev))
return 0;
- status = acpi_bus_get_device(dev->archdata.acpi_handle,
- &acpi_dev);
+ status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
if (ACPI_FAILURE(status))
goto err;
@@ -228,7 +246,7 @@ static int acpi_unbind_one(struct device *dev)
sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
sysfs_remove_link(&dev->kobj, "firmware_node");
- dev->archdata.acpi_handle = NULL;
+ ACPI_HANDLE_SET(dev, NULL);
/* acpi_bind_one increase refcnt by one */
put_device(dev);
kfree(entry);
@@ -248,6 +266,10 @@ static int acpi_platform_notify(struct device *dev)
acpi_handle handle;
int ret = -EINVAL;
+ ret = acpi_bind_one(dev, NULL);
+ if (!ret)
+ goto out;
+
if (!dev->bus || !dev->parent) {
/* bridge devices genernally haven't bus or parent */
ret = acpi_find_bridge_device(dev, &handle);
@@ -261,16 +283,16 @@ static int acpi_platform_notify(struct device *dev)
}
if ((ret = type->find_device(dev, &handle)) != 0)
DBG("Can't get handler for %s\n", dev_name(dev));
- end:
+ end:
if (!ret)
acpi_bind_one(dev, handle);
+ out:
#if ACPI_GLUE_DEBUG
if (!ret) {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- acpi_get_name(dev->archdata.acpi_handle,
- ACPI_FULL_PATHNAME, &buffer);
+ acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
kfree(buffer.pointer);
} else
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 20a0f2c3ca3b..a0cc796932f7 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -61,7 +61,7 @@ static void acpi_hed_notify(struct acpi_device *device, u32 event)
blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL);
}
-static int __devinit acpi_hed_add(struct acpi_device *device)
+static int acpi_hed_add(struct acpi_device *device)
{
/* Only one hardware error device */
if (hed_handle)
@@ -70,7 +70,7 @@ static int __devinit acpi_hed_add(struct acpi_device *device)
return 0;
}
-static int __devexit acpi_hed_remove(struct acpi_device *device, int type)
+static int acpi_hed_remove(struct acpi_device *device, int type)
{
hed_handle = NULL;
return 0;
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index ca75b9ce0489..3c407cdc1ec1 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -58,11 +58,11 @@ struct acpi_ec {
unsigned long data_addr;
unsigned long global_lock;
unsigned long flags;
- struct mutex lock;
+ struct mutex mutex;
wait_queue_head_t wait;
struct list_head list;
struct transaction *curr;
- spinlock_t curr_lock;
+ spinlock_t lock;
};
extern struct acpi_ec *first_ec;
@@ -93,4 +93,11 @@ static inline int suspend_nvs_save(void) { return 0; }
static inline void suspend_nvs_restore(void) {}
#endif
+/*--------------------------------------------------------------------------
+ Platform bus support
+ -------------------------------------------------------------------------- */
+struct platform_device;
+
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
+
#endif /* _ACPI_INTERNAL_H_ */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 9eaf708f5885..6dc4a2b1e956 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -932,7 +932,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
* having a static work_struct.
*/
- dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
+ dpc = kzalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
if (!dpc)
return AE_NO_MEMORY;
@@ -944,17 +944,22 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
* because the hotplug code may call driver .remove() functions,
* which invoke flush_scheduled_work/acpi_os_wait_events_complete
* to flush these workqueues.
+ *
+ * To prevent lockdep from complaining unnecessarily, make sure that
+ * there is a different static lockdep key for each workqueue by using
+ * INIT_WORK() for each of them separately.
*/
- queue = hp ? kacpi_hotplug_wq :
- (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
- dpc->wait = hp ? 1 : 0;
-
- if (queue == kacpi_hotplug_wq)
+ if (hp) {
+ queue = kacpi_hotplug_wq;
+ dpc->wait = 1;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
- else if (queue == kacpi_notify_wq)
+ } else if (type == OSL_NOTIFY_HANDLER) {
+ queue = kacpi_notify_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
- else
+ } else {
+ queue = kacpid_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+ }
/*
* On some machines, a software-initiated SMI causes corruption unless
@@ -986,6 +991,7 @@ acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
{
return __acpi_os_execute(0, function, context, 1);
}
+EXPORT_SYMBOL(acpi_os_hotplug_execute);
void acpi_os_wait_events_complete(void)
{
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 0eefa12e648c..23a032490130 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -459,19 +459,19 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
*/
if (gsi < 0) {
u32 dev_gsi;
- dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF) &&
(acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
- printk(" - using ISA IRQ %d\n", dev->irq);
+ dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
+ pin_name(pin), dev->irq);
acpi_register_gsi(&dev->dev, dev_gsi,
ACPI_LEVEL_SENSITIVE,
ACPI_ACTIVE_LOW);
- return 0;
} else {
- printk("\n");
- return 0;
+ dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
+ pin_name(pin));
}
+ return 0;
}
rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
@@ -495,11 +495,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
return 0;
}
-/* FIXME: implement x86/x86_64 version */
-void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
-{
-}
-
void acpi_pci_irq_disable(struct pci_dev *dev)
{
struct acpi_prt_entry *entry;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index bce469c0b48a..f70b9e5fc1b5 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -445,7 +445,7 @@ out:
}
EXPORT_SYMBOL(acpi_pci_osc_control_set);
-static int __devinit acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device)
{
unsigned long long segment, bus;
acpi_status status;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 40e38a06ba85..7db61b8fa11f 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -473,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
return ret;
no_power_resource:
- printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
+ printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!\n");
return -ENODEV;
}
EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 27adb090bb30..ef98796b3824 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -362,16 +362,13 @@ acpi_system_write_wakeup_device(struct file *file,
struct list_head *node, *next;
char strbuf[5];
char str[5] = "";
- unsigned int len = count;
- if (len > 4)
- len = 4;
- if (len < 0)
- return -EFAULT;
+ if (count > 4)
+ count = 4;
- if (copy_from_user(strbuf, buffer, len))
+ if (copy_from_user(strbuf, buffer, count))
return -EFAULT;
- strbuf[len] = '\0';
+ strbuf[count] = '\0';
sscanf(strbuf, "%s", str);
mutex_lock(&acpi_device_lock);
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index bd4e5dca3ff7..e83311bf1ebd 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -44,6 +44,7 @@
#include <linux/moduleparam.h>
#include <linux/cpuidle.h>
#include <linux/slab.h>
+#include <linux/acpi.h>
#include <asm/io.h>
#include <asm/cpu.h>
@@ -282,7 +283,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
/* Declared with "Processor" statement; match ProcessorID */
status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX "Evaluating processor object\n");
+ dev_err(&device->dev,
+ "Failed to evaluate processor object (0x%x)\n",
+ status);
return -ENODEV;
}
@@ -301,8 +304,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
NULL, &value);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR PREFIX
- "Evaluating processor _UID [%#x]\n", status);
+ dev_err(&device->dev,
+ "Failed to evaluate processor _UID (0x%x)\n",
+ status);
return -ENODEV;
}
device_declaration = 1;
@@ -345,7 +349,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
if (!object.processor.pblk_address)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
else if (object.processor.pblk_length != 6)
- printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+ dev_err(&device->dev, "Invalid PBLK length [%d]\n",
object.processor.pblk_length);
else {
pr->throttling.address = object.processor.pblk_address;
@@ -430,8 +434,8 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
* Initialize missing things
*/
if (pr->flags.need_hotplug_init) {
- printk(KERN_INFO "Will online and init hotplugged "
- "CPU: %d\n", pr->id);
+ pr_info("Will online and init hotplugged CPU: %d\n",
+ pr->id);
WARN(acpi_processor_start(pr), "Failed to start CPU:"
" %d\n", pr->id);
pr->flags.need_hotplug_init = 0;
@@ -492,14 +496,16 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
&pr->cdev->device.kobj,
"thermal_cooling");
if (result) {
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&device->dev,
+ "Failed to create sysfs link 'thermal_cooling'\n");
goto err_thermal_unregister;
}
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj,
"device");
if (result) {
- printk(KERN_ERR PREFIX "Create sysfs link\n");
+ dev_err(&pr->cdev->device,
+ "Failed to create sysfs link 'device'\n");
goto err_remove_sysfs_thermal;
}
@@ -561,8 +567,9 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
*/
if (per_cpu(processor_device_array, pr->id) != NULL &&
per_cpu(processor_device_array, pr->id) != device) {
- printk(KERN_WARNING "BIOS reported wrong ACPI id "
- "for the processor\n");
+ dev_warn(&device->dev,
+ "BIOS reported wrong ACPI id %d for the processor\n",
+ pr->id);
result = -ENODEV;
goto err_free_cpumask;
}
@@ -695,8 +702,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
static void acpi_processor_hotplug_notify(acpi_handle handle,
u32 event, void *data)
{
- struct acpi_processor *pr;
struct acpi_device *device = NULL;
+ struct acpi_eject_event *ej_event = NULL;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
int result;
@@ -716,7 +723,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
result = acpi_processor_device_add(handle, &device);
if (result) {
- printk(KERN_ERR PREFIX "Unable to add the device\n");
+ acpi_handle_err(handle, "Unable to add the device\n");
break;
}
@@ -728,20 +735,29 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
"received ACPI_NOTIFY_EJECT_REQUEST\n"));
if (acpi_bus_get_device(handle, &device)) {
- printk(KERN_ERR PREFIX
- "Device don't exist, dropping EJECT\n");
+ acpi_handle_err(handle,
+ "Device don't exist, dropping EJECT\n");
break;
}
- pr = acpi_driver_data(device);
- if (!pr) {
- printk(KERN_ERR PREFIX
- "Driver data is NULL, dropping EJECT\n");
+ if (!acpi_driver_data(device)) {
+ acpi_handle_err(handle,
+ "Driver data is NULL, dropping EJECT\n");
break;
}
- /* REVISIT: update when eject is supported */
- ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
- break;
+ ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+ if (!ej_event) {
+ acpi_handle_err(handle, "No memory, dropping EJECT\n");
+ break;
+ }
+
+ ej_event->handle = handle;
+ ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+ acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+ (void *)ej_event);
+
+ /* eject is performed asynchronously */
+ return;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -841,7 +857,7 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
* and do it when the CPU gets online the first time
* TBD: Cleanup above functions and try to do this more elegant.
*/
- printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+ pr_info("CPU %d got hotplugged\n", pr->id);
pr->flags.need_hotplug_init = 1;
return AE_OK;
@@ -852,8 +868,22 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr)
if (cpu_online(pr->id))
cpu_down(pr->id);
+ get_online_cpus();
+ /*
+ * The cpu might become online again at this point. So we check whether
+ * the cpu has been onlined or not. If the cpu became online, it means
+ * that someone wants to use the cpu. So acpi_processor_handle_eject()
+ * returns -EAGAIN.
+ */
+ if (unlikely(cpu_online(pr->id))) {
+ put_online_cpus();
+ pr_warn("Failed to remove CPU %d, because other task "
+ "brought the CPU back online\n", pr->id);
+ return -EAGAIN;
+ }
arch_unregister_cpu(pr->id);
acpi_unmap_lsapic(pr->id);
+ put_online_cpus();
return (0);
}
#else
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index e8086c725305..f1a5da44591d 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -735,31 +735,18 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
static int acpi_idle_enter_c1(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- ktime_t kt1, kt2;
- s64 idle_time;
struct acpi_processor *pr;
struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
pr = __this_cpu_read(processors);
- dev->last_residency = 0;
if (unlikely(!pr))
return -EINVAL;
- local_irq_disable();
-
-
lapic_timer_state_broadcast(pr, cx, 1);
- kt1 = ktime_get_real();
acpi_idle_do_entry(cx);
- kt2 = ktime_get_real();
- idle_time = ktime_to_us(ktime_sub(kt2, kt1));
-
- /* Update device last_residency*/
- dev->last_residency = (int)idle_time;
- local_irq_enable();
lapic_timer_state_broadcast(pr, cx, 0);
return index;
@@ -806,19 +793,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
struct acpi_processor *pr;
struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
- ktime_t kt1, kt2;
- s64 idle_time_ns;
- s64 idle_time;
pr = __this_cpu_read(processors);
- dev->last_residency = 0;
if (unlikely(!pr))
return -EINVAL;
- local_irq_disable();
-
-
if (cx->entry_method != ACPI_CSTATE_FFH) {
current_thread_info()->status &= ~TS_POLLING;
/*
@@ -829,7 +809,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;
- local_irq_enable();
return -EINVAL;
}
}
@@ -843,22 +822,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (cx->type == ACPI_STATE_C3)
ACPI_FLUSH_CPU_CACHE();
- kt1 = ktime_get_real();
/* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event();
acpi_idle_do_entry(cx);
- kt2 = ktime_get_real();
- idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
- idle_time = idle_time_ns;
- do_div(idle_time, NSEC_PER_USEC);
- /* Update device last_residency*/
- dev->last_residency = (int)idle_time;
+ sched_clock_idle_wakeup_event(0);
- /* Tell the scheduler how much we idled: */
- sched_clock_idle_wakeup_event(idle_time_ns);
-
- local_irq_enable();
if (cx->entry_method != ACPI_CSTATE_FFH)
current_thread_info()->status |= TS_POLLING;
@@ -883,13 +852,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
struct acpi_processor *pr;
struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
- ktime_t kt1, kt2;
- s64 idle_time_ns;
- s64 idle_time;
-
pr = __this_cpu_read(processors);
- dev->last_residency = 0;
if (unlikely(!pr))
return -EINVAL;
@@ -899,16 +863,11 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
return drv->states[drv->safe_state_index].enter(dev,
drv, drv->safe_state_index);
} else {
- local_irq_disable();
acpi_safe_halt();
- local_irq_enable();
return -EBUSY;
}
}
- local_irq_disable();
-
-
if (cx->entry_method != ACPI_CSTATE_FFH) {
current_thread_info()->status &= ~TS_POLLING;
/*
@@ -919,7 +878,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (unlikely(need_resched())) {
current_thread_info()->status |= TS_POLLING;
- local_irq_enable();
return -EINVAL;
}
}
@@ -934,7 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
*/
lapic_timer_state_broadcast(pr, cx, 1);
- kt1 = ktime_get_real();
/*
* disable bus master
* bm_check implies we need ARB_DIS
@@ -965,18 +922,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
c3_cpu_count--;
raw_spin_unlock(&c3_lock);
}
- kt2 = ktime_get_real();
- idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
- idle_time = idle_time_ns;
- do_div(idle_time, NSEC_PER_USEC);
-
- /* Update device last_residency*/
- dev->last_residency = (int)idle_time;
- /* Tell the scheduler how much we idled: */
- sched_clock_idle_wakeup_event(idle_time_ns);
+ sched_clock_idle_wakeup_event(0);
- local_irq_enable();
if (cx->entry_method != ACPI_CSTATE_FFH)
current_thread_info()->status |= TS_POLLING;
@@ -987,6 +935,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
struct cpuidle_driver acpi_idle_driver = {
.name = "acpi_idle",
.owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
};
/**
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
new file mode 100644
index 000000000000..a3868f6c222a
--- /dev/null
+++ b/drivers/acpi/resource.c
@@ -0,0 +1,526 @@
+/*
+ * drivers/acpi/resource.c - ACPI device resources interpretation.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_X86
+#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
+#else
+#define valid_IRQ(i) (true)
+#endif
+
+static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
+ bool window)
+{
+ unsigned long flags = IORESOURCE_MEM;
+
+ if (len == 0)
+ flags |= IORESOURCE_DISABLED;
+
+ if (write_protect == ACPI_READ_WRITE_MEMORY)
+ flags |= IORESOURCE_MEM_WRITEABLE;
+
+ if (window)
+ flags |= IORESOURCE_WINDOW;
+
+ return flags;
+}
+
+static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
+ u8 write_protect)
+{
+ res->start = start;
+ res->end = start + len - 1;
+ res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+}
+
+/**
+ * acpi_dev_resource_memory - Extract ACPI memory resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents a memory resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
+{
+ struct acpi_resource_memory24 *memory24;
+ struct acpi_resource_memory32 *memory32;
+ struct acpi_resource_fixed_memory32 *fixed_memory32;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_MEMORY24:
+ memory24 = &ares->data.memory24;
+ acpi_dev_get_memresource(res, memory24->minimum,
+ memory24->address_length,
+ memory24->write_protect);
+ break;
+ case ACPI_RESOURCE_TYPE_MEMORY32:
+ memory32 = &ares->data.memory32;
+ acpi_dev_get_memresource(res, memory32->minimum,
+ memory32->address_length,
+ memory32->write_protect);
+ break;
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+ fixed_memory32 = &ares->data.fixed_memory32;
+ acpi_dev_get_memresource(res, fixed_memory32->address,
+ fixed_memory32->address_length,
+ fixed_memory32->write_protect);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
+
+static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
+ bool window)
+{
+ int flags = IORESOURCE_IO;
+
+ if (io_decode == ACPI_DECODE_16)
+ flags |= IORESOURCE_IO_16BIT_ADDR;
+
+ if (start > end || end >= 0x10003)
+ flags |= IORESOURCE_DISABLED;
+
+ if (window)
+ flags |= IORESOURCE_WINDOW;
+
+ return flags;
+}
+
+static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
+ u8 io_decode)
+{
+ u64 end = start + len - 1;
+
+ res->start = start;
+ res->end = end;
+ res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
+}
+
+/**
+ * acpi_dev_resource_io - Extract ACPI I/O resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an I/O resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
+{
+ struct acpi_resource_io *io;
+ struct acpi_resource_fixed_io *fixed_io;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_IO:
+ io = &ares->data.io;
+ acpi_dev_get_ioresource(res, io->minimum,
+ io->address_length,
+ io->io_decode);
+ break;
+ case ACPI_RESOURCE_TYPE_FIXED_IO:
+ fixed_io = &ares->data.fixed_io;
+ acpi_dev_get_ioresource(res, fixed_io->address,
+ fixed_io->address_length,
+ ACPI_DECODE_10);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
+
+/**
+ * acpi_dev_resource_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an address space resource
+ * and if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+ struct resource *res)
+{
+ acpi_status status;
+ struct acpi_resource_address64 addr;
+ bool window;
+ u64 len;
+ u8 io_decode;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_ADDRESS16:
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ case ACPI_RESOURCE_TYPE_ADDRESS64:
+ break;
+ default:
+ return false;
+ }
+
+ status = acpi_resource_to_address64(ares, &addr);
+ if (ACPI_FAILURE(status))
+ return true;
+
+ res->start = addr.minimum;
+ res->end = addr.maximum;
+ window = addr.producer_consumer == ACPI_PRODUCER;
+
+ switch(addr.resource_type) {
+ case ACPI_MEMORY_RANGE:
+ len = addr.maximum - addr.minimum + 1;
+ res->flags = acpi_dev_memresource_flags(len,
+ addr.info.mem.write_protect,
+ window);
+ break;
+ case ACPI_IO_RANGE:
+ io_decode = addr.granularity == 0xfff ?
+ ACPI_DECODE_10 : ACPI_DECODE_16;
+ res->flags = acpi_dev_ioresource_flags(addr.minimum,
+ addr.maximum,
+ io_decode, window);
+ break;
+ case ACPI_BUS_NUMBER_RANGE:
+ res->flags = IORESOURCE_BUS;
+ break;
+ default:
+ res->flags = 0;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
+
+/**
+ * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an extended address space
+ * resource and if that's the case, use the information in it to populate the
+ * generic resource object pointed to by @res.
+ */
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+ struct resource *res)
+{
+ struct acpi_resource_extended_address64 *ext_addr;
+ bool window;
+ u64 len;
+ u8 io_decode;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
+ return false;
+
+ ext_addr = &ares->data.ext_address64;
+
+ res->start = ext_addr->minimum;
+ res->end = ext_addr->maximum;
+ window = ext_addr->producer_consumer == ACPI_PRODUCER;
+
+ switch(ext_addr->resource_type) {
+ case ACPI_MEMORY_RANGE:
+ len = ext_addr->maximum - ext_addr->minimum + 1;
+ res->flags = acpi_dev_memresource_flags(len,
+ ext_addr->info.mem.write_protect,
+ window);
+ break;
+ case ACPI_IO_RANGE:
+ io_decode = ext_addr->granularity == 0xfff ?
+ ACPI_DECODE_10 : ACPI_DECODE_16;
+ res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
+ ext_addr->maximum,
+ io_decode, window);
+ break;
+ case ACPI_BUS_NUMBER_RANGE:
+ res->flags = IORESOURCE_BUS;
+ break;
+ default:
+ res->flags = 0;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
+
+/**
+ * acpi_dev_irq_flags - Determine IRQ resource flags.
+ * @triggering: Triggering type as provided by ACPI.
+ * @polarity: Interrupt polarity as provided by ACPI.
+ * @shareable: Whether or not the interrupt is shareable.
+ */
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
+{
+ unsigned long flags;
+
+ if (triggering == ACPI_LEVEL_SENSITIVE)
+ flags = polarity == ACPI_ACTIVE_LOW ?
+ IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
+ else
+ flags = polarity == ACPI_ACTIVE_LOW ?
+ IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
+
+ if (shareable == ACPI_SHARED)
+ flags |= IORESOURCE_IRQ_SHAREABLE;
+
+ return flags | IORESOURCE_IRQ;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
+
+static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
+{
+ res->start = gsi;
+ res->end = gsi;
+ res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED;
+}
+
+static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
+ u8 triggering, u8 polarity, u8 shareable)
+{
+ int irq, p, t;
+
+ if (!valid_IRQ(gsi)) {
+ acpi_dev_irqresource_disabled(res, gsi);
+ return;
+ }
+
+ /*
+ * In IO-APIC mode, use overrided attribute. Two reasons:
+ * 1. BIOS bug in DSDT
+ * 2. BIOS uses IO-APIC mode Interrupt Source Override
+ */
+ if (!acpi_get_override_irq(gsi, &t, &p)) {
+ u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+ u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+ if (triggering != trig || polarity != pol) {
+ pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
+ t ? "edge" : "level", p ? "low" : "high");
+ triggering = trig;
+ polarity = pol;
+ }
+ }
+
+ res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
+ irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
+ if (irq >= 0) {
+ res->start = irq;
+ res->end = irq;
+ } else {
+ acpi_dev_irqresource_disabled(res, gsi);
+ }
+}
+
+/**
+ * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
+ * @ares: Input ACPI resource object.
+ * @index: Index into the array of GSIs represented by the resource.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an interrupt resource
+ * and @index does not exceed the resource's interrupt count (true is returned
+ * in that case regardless of the results of the other checks)). If that's the
+ * case, register the GSI corresponding to @index from the array of interrupts
+ * represented by the resource and populate the generic resource object pointed
+ * to by @res accordingly. If the registration of the GSI is not successful,
+ * IORESOURCE_DISABLED will be set it that object's flags.
+ */
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+ struct resource *res)
+{
+ struct acpi_resource_irq *irq;
+ struct acpi_resource_extended_irq *ext_irq;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+ /*
+ * Per spec, only one interrupt per descriptor is allowed in
+ * _CRS, but some firmware violates this, so parse them all.
+ */
+ irq = &ares->data.irq;
+ if (index >= irq->interrupt_count) {
+ acpi_dev_irqresource_disabled(res, 0);
+ return false;
+ }
+ acpi_dev_get_irqresource(res, irq->interrupts[index],
+ irq->triggering, irq->polarity,
+ irq->sharable);
+ break;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ ext_irq = &ares->data.extended_irq;
+ if (index >= ext_irq->interrupt_count) {
+ acpi_dev_irqresource_disabled(res, 0);
+ return false;
+ }
+ acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
+ ext_irq->triggering, ext_irq->polarity,
+ ext_irq->sharable);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
+
+/**
+ * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
+ * @list: The head of the resource list to free.
+ */
+void acpi_dev_free_resource_list(struct list_head *list)
+{
+ struct resource_list_entry *rentry, *re;
+
+ list_for_each_entry_safe(rentry, re, list, node) {
+ list_del(&rentry->node);
+ kfree(rentry);
+ }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
+
+struct res_proc_context {
+ struct list_head *list;
+ int (*preproc)(struct acpi_resource *, void *);
+ void *preproc_data;
+ int count;
+ int error;
+};
+
+static acpi_status acpi_dev_new_resource_entry(struct resource *r,
+ struct res_proc_context *c)
+{
+ struct resource_list_entry *rentry;
+
+ rentry = kmalloc(sizeof(*rentry), GFP_KERNEL);
+ if (!rentry) {
+ c->error = -ENOMEM;
+ return AE_NO_MEMORY;
+ }
+ rentry->res = *r;
+ list_add_tail(&rentry->node, c->list);
+ c->count++;
+ return AE_OK;
+}
+
+static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
+ void *context)
+{
+ struct res_proc_context *c = context;
+ struct resource r;
+ int i;
+
+ if (c->preproc) {
+ int ret;
+
+ ret = c->preproc(ares, c->preproc_data);
+ if (ret < 0) {
+ c->error = ret;
+ return AE_CTRL_TERMINATE;
+ } else if (ret > 0) {
+ return AE_OK;
+ }
+ }
+
+ memset(&r, 0, sizeof(r));
+
+ if (acpi_dev_resource_memory(ares, &r)
+ || acpi_dev_resource_io(ares, &r)
+ || acpi_dev_resource_address_space(ares, &r)
+ || acpi_dev_resource_ext_address_space(ares, &r))
+ return acpi_dev_new_resource_entry(&r, c);
+
+ for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) {
+ acpi_status status;
+
+ status = acpi_dev_new_resource_entry(&r, c);
+ if (ACPI_FAILURE(status))
+ return status;
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_dev_get_resources - Get current resources of a device.
+ * @adev: ACPI device node to get the resources for.
+ * @list: Head of the resultant list of resources (must be empty).
+ * @preproc: The caller's preprocessing routine.
+ * @preproc_data: Pointer passed to the caller's preprocessing routine.
+ *
+ * Evaluate the _CRS method for the given device node and process its output by
+ * (1) executing the @preproc() rountine provided by the caller, passing the
+ * resource pointer and @preproc_data to it as arguments, for each ACPI resource
+ * returned and (2) converting all of the returned ACPI resources into struct
+ * resource objects if possible. If the return value of @preproc() in step (1)
+ * is different from 0, step (2) is not applied to the given ACPI resource and
+ * if that value is negative, the whole processing is aborted and that value is
+ * returned as the final error code.
+ *
+ * The resultant struct resource objects are put on the list pointed to by
+ * @list, that must be empty initially, as members of struct resource_list_entry
+ * objects. Callers of this routine should use %acpi_dev_free_resource_list() to
+ * free that list.
+ *
+ * The number of resources in the output list is returned on success, an error
+ * code reflecting the error condition is returned otherwise.
+ */
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+ int (*preproc)(struct acpi_resource *, void *),
+ void *preproc_data)
+{
+ struct res_proc_context c;
+ acpi_handle not_used;
+ acpi_status status;
+
+ if (!adev || !adev->handle || !list_empty(list))
+ return -EINVAL;
+
+ status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, &not_used);
+ if (ACPI_FAILURE(status))
+ return 0;
+
+ c.list = list;
+ c.preproc = preproc;
+ c.preproc_data = preproc_data;
+ c.count = 0;
+ c.error = 0;
+ status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
+ acpi_dev_process_resource, &c);
+ if (ACPI_FAILURE(status)) {
+ acpi_dev_free_resource_list(list);
+ return c.error ? c.error : -EIO;
+ }
+
+ return c.count;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1fcb8678665c..53502d1bbf26 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -29,6 +29,27 @@ extern struct acpi_device *acpi_root;
static const char *dummy_hid = "device";
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+ { "PNP0D40" },
+
+ /* Haswell LPSS devices */
+ { "INT33C0", 0 },
+ { "INT33C1", 0 },
+ { "INT33C2", 0 },
+ { "INT33C3", 0 },
+ { "INT33C4", 0 },
+ { "INT33C5", 0 },
+ { "INT33C6", 0 },
+ { "INT33C7", 0 },
+
+ { }
+};
+
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
DEFINE_MUTEX(acpi_device_lock);
@@ -97,6 +118,7 @@ void acpi_bus_hot_remove_device(void *context)
struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
struct acpi_device *device;
acpi_handle handle = ej_event->handle;
+ acpi_handle temp;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
@@ -117,13 +139,16 @@ void acpi_bus_hot_remove_device(void *context)
goto err_out;
}
+ /* device has been freed */
+ device = NULL;
+
/* power off device */
status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
printk(KERN_WARNING PREFIX
"Power-off device failed\n");
- if (device->flags.lockable) {
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
@@ -157,6 +182,7 @@ err_out:
kfree(context);
return;
}
+EXPORT_SYMBOL(acpi_bus_hot_remove_device);
static ssize_t
acpi_eject_store(struct device *d, struct device_attribute *attr,
@@ -216,6 +242,25 @@ acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *bu
}
static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+static ssize_t acpi_device_uid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+
+static ssize_t acpi_device_adr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "0x%08x\n",
+ (unsigned int)(acpi_dev->pnp.bus_address));
+}
+static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
+
static ssize_t
acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -259,11 +304,21 @@ static ssize_t description_show(struct device *dev,
}
static DEVICE_ATTR(description, 0444, description_show, NULL);
+static ssize_t
+acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
+ char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "%lu\n", acpi_dev->pnp.sun);
+}
+static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+
static int acpi_device_setup_files(struct acpi_device *dev)
{
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status;
acpi_handle temp;
+ unsigned long long sun;
int result = 0;
/*
@@ -300,6 +355,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
goto end;
}
+ if (dev->flags.bus_address)
+ result = device_create_file(&dev->dev, &dev_attr_adr);
+ if (dev->pnp.unique_id)
+ result = device_create_file(&dev->dev, &dev_attr_uid);
+
+ status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun);
+ if (ACPI_SUCCESS(status)) {
+ dev->pnp.sun = (unsigned long)sun;
+ result = device_create_file(&dev->dev, &dev_attr_sun);
+ if (result)
+ goto end;
+ } else {
+ dev->pnp.sun = (unsigned long)-1;
+ }
+
/*
* If device has _EJ0, 'eject' file is created that is used to trigger
* hot-removal function from userland.
@@ -331,6 +401,14 @@ static void acpi_device_remove_files(struct acpi_device *dev)
if (ACPI_SUCCESS(status))
device_remove_file(&dev->dev, &dev_attr_eject);
+ status = acpi_get_handle(dev->handle, "_SUN", &temp);
+ if (ACPI_SUCCESS(status))
+ device_remove_file(&dev->dev, &dev_attr_sun);
+
+ if (dev->pnp.unique_id)
+ device_remove_file(&dev->dev, &dev_attr_uid);
+ if (dev->flags.bus_address)
+ device_remove_file(&dev->dev, &dev_attr_adr);
device_remove_file(&dev->dev, &dev_attr_modalias);
device_remove_file(&dev->dev, &dev_attr_hid);
if (dev->handle)
@@ -340,8 +418,8 @@ static void acpi_device_remove_files(struct acpi_device *dev)
ACPI Bus operations
-------------------------------------------------------------------------- */
-int acpi_match_device_ids(struct acpi_device *device,
- const struct acpi_device_id *ids)
+static const struct acpi_device_id *__acpi_match_device(
+ struct acpi_device *device, const struct acpi_device_id *ids)
{
const struct acpi_device_id *id;
struct acpi_hardware_id *hwid;
@@ -351,14 +429,44 @@ int acpi_match_device_ids(struct acpi_device *device,
* driver for it.
*/
if (!device->status.present)
- return -ENODEV;
+ return NULL;
for (id = ids; id->id[0]; id++)
list_for_each_entry(hwid, &device->pnp.ids, list)
if (!strcmp((char *) id->id, hwid->id))
- return 0;
+ return id;
- return -ENOENT;
+ return NULL;
+}
+
+/**
+ * acpi_match_device - Match a struct device against a given list of ACPI IDs
+ * @ids: Array of struct acpi_device_id object to match against.
+ * @dev: The device structure to match.
+ *
+ * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
+ * object for that handle and use that object to match against a given list of
+ * device IDs.
+ *
+ * Return a pointer to the first matching ID on success or %NULL on failure.
+ */
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ const struct device *dev)
+{
+ struct acpi_device *adev;
+
+ if (!ids || !ACPI_HANDLE(dev)
+ || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev)))
+ return NULL;
+
+ return __acpi_match_device(adev, ids);
+}
+EXPORT_SYMBOL_GPL(acpi_match_device);
+
+int acpi_match_device_ids(struct acpi_device *device,
+ const struct acpi_device_id *ids)
+{
+ return __acpi_match_device(device, ids) ? 0 : -ENOENT;
}
EXPORT_SYMBOL(acpi_match_device_ids);
@@ -377,6 +485,7 @@ static void acpi_device_release(struct device *dev)
struct acpi_device *acpi_dev = to_acpi_device(dev);
acpi_free_ids(acpi_dev);
+ kfree(acpi_dev->pnp.unique_id);
kfree(acpi_dev);
}
@@ -859,8 +968,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
{
struct acpi_device_id button_device_ids[] = {
- {"PNP0C0D", 0},
{"PNP0C0C", 0},
+ {"PNP0C0D", 0},
{"PNP0C0E", 0},
{"", 0},
};
@@ -872,6 +981,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids)) {
device->wakeup.flags.run_wake = 1;
+ if (!acpi_match_device_ids(device, &button_device_ids[1])) {
+ /* Do not use Lid/sleep button for S5 wakeup */
+ if (device->wakeup.sleep_state == ACPI_STATE_S5)
+ device->wakeup.sleep_state = ACPI_STATE_S4;
+ }
device_set_wakeup_capable(&device->dev, true);
return;
}
@@ -965,8 +1079,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
* D3hot is only valid if _PR3 present.
*/
if (ps->resources.count ||
- (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
+ (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) {
ps->flags.valid = 1;
+ ps->flags.os_accessible = 1;
+ }
ps->power = -1; /* Unknown - driver assigned */
ps->latency = -1; /* Unknown - driver assigned */
@@ -982,6 +1098,11 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1;
+ /* Presence of _PS3 or _PRx means we can put the device into D3 cold */
+ if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set ||
+ device->power.flags.power_resources)
+ device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
+
acpi_bus_init_power(device);
return 0;
@@ -1013,11 +1134,6 @@ static int acpi_bus_get_flags(struct acpi_device *device)
device->flags.ejectable = 1;
}
- /* Presence of _LCK indicates 'lockable' */
- status = acpi_get_handle(device->handle, "_LCK", &temp);
- if (ACPI_SUCCESS(status))
- device->flags.lockable = 1;
-
/* Power resources cannot be power manageable. */
if (device->device_type == ACPI_BUS_TYPE_POWER)
return 0;
@@ -1185,7 +1301,7 @@ static void acpi_device_set_id(struct acpi_device *device)
{
acpi_status status;
struct acpi_device_info *info;
- struct acpica_device_id_list *cid_list;
+ struct acpi_pnp_device_id_list *cid_list;
int i;
switch (device->device_type) {
@@ -1212,6 +1328,9 @@ static void acpi_device_set_id(struct acpi_device *device)
device->pnp.bus_address = info->address;
device->flags.bus_address = 1;
}
+ if (info->valid & ACPI_VALID_UID)
+ device->pnp.unique_id = kstrdup(info->unique_id.string,
+ GFP_KERNEL);
kfree(info);
@@ -1483,8 +1602,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
*/
device = NULL;
acpi_bus_get_device(handle, &device);
- if (ops->acpi_op_add && !device)
+ if (ops->acpi_op_add && !device) {
acpi_add_single_object(&device, handle, type, sta, ops);
+ /* Is the device a known good platform device? */
+ if (device
+ && !acpi_match_device_ids(device, acpi_platform_device_ids))
+ acpi_create_platform_device(device);
+ }
if (!device)
return AE_CTRL_DEPTH;
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index fdcdbb652915..2fcc67d34b11 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -18,7 +18,6 @@
#include <linux/reboot.h>
#include <linux/acpi.h>
#include <linux/module.h>
-#include <linux/pm_runtime.h>
#include <asm/io.h>
@@ -81,6 +80,12 @@ static int acpi_sleep_prepare(u32 acpi_state)
#ifdef CONFIG_ACPI_SLEEP
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
+u32 acpi_target_system_state(void)
+{
+ return acpi_target_sleep_state;
+}
+
static bool pwr_btn_event_pending;
/*
@@ -98,6 +103,21 @@ void __init acpi_nvs_nosave(void)
}
/*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * but says nothing about saving NVS during S3. Not all versions of Windows
+ * save NVS on S3 suspend either, and it is clear that not all systems need
+ * NVS to be saved at S3 time. To improve suspend/resume time, allow the
+ * user to disable saving NVS on S3 if their system does not require it, but
+ * continue to save/restore NVS for S4 as specified.
+ */
+static bool nvs_nosave_s3;
+
+void __init acpi_nvs_nosave_s3(void)
+{
+ nvs_nosave_s3 = true;
+}
+
+/*
* ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
* user to request that behavior by using the 'acpi_old_suspend_ordering'
* kernel command line option that causes the following variable to be set.
@@ -109,6 +129,180 @@ void __init acpi_old_suspend_ordering(void)
old_suspend_ordering = true;
}
+static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
+{
+ acpi_old_suspend_ordering();
+ return 0;
+}
+
+static int __init init_nvs_nosave(const struct dmi_system_id *d)
+{
+ acpi_nvs_nosave();
+ return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Abit KN9 (nForce4 variant)",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+ DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
+ },
+ },
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "HP xw4600 Workstation",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
+ },
+ },
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
+ },
+ },
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Panasonic CF51-2L",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR,
+ "Matsushita Electric Industrial Co.,Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-FW21E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCEB17FX",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-SR11M",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Everex StepNote Series",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCEB1Z1E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-NW130D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCCW29FX",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Averatec AV1020-ED2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
+ },
+ },
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Asus A8N-SLI DELUXE",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
+ },
+ },
+ {
+ .callback = init_old_suspend_ordering,
+ .ident = "Asus A8N-SLI Premium",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-SR26GN_P",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCEB1S1E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Sony Vaio VGN-FW520F",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Asus K54C",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Asus K54HR",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
+ },
+ },
+ {},
+};
+
+static void acpi_sleep_dmi_check(void)
+{
+ dmi_check_system(acpisleep_dmi_table);
+}
+
/**
* acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
*/
@@ -224,6 +418,7 @@ static void acpi_pm_end(void)
}
#else /* !CONFIG_ACPI_SLEEP */
#define acpi_target_sleep_state ACPI_STATE_S0
+static inline void acpi_sleep_dmi_check(void) {}
#endif /* CONFIG_ACPI_SLEEP */
#ifdef CONFIG_SUSPEND
@@ -243,7 +438,7 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
- error = nvs_nosave ? 0 : suspend_nvs_alloc();
+ error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
if (error)
return error;
@@ -382,167 +577,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
-
-static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
-{
- old_suspend_ordering = true;
- return 0;
-}
-
-static int __init init_nvs_nosave(const struct dmi_system_id *d)
-{
- acpi_nvs_nosave();
- return 0;
-}
-
-static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
- {
- .callback = init_old_suspend_ordering,
- .ident = "Abit KN9 (nForce4 variant)",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
- DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
- },
- },
- {
- .callback = init_old_suspend_ordering,
- .ident = "HP xw4600 Workstation",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
- },
- },
- {
- .callback = init_old_suspend_ordering,
- .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
- },
- },
- {
- .callback = init_old_suspend_ordering,
- .ident = "Panasonic CF51-2L",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR,
- "Matsushita Electric Industrial Co.,Ltd."),
- DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-FW21E",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VPCEB17FX",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-SR11M",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Everex StepNote Series",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VPCEB1Z1E",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-NW130D",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VPCCW29FX",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Averatec AV1020-ED2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
- DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
- },
- },
- {
- .callback = init_old_suspend_ordering,
- .ident = "Asus A8N-SLI DELUXE",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
- },
- },
- {
- .callback = init_old_suspend_ordering,
- .ident = "Asus A8N-SLI Premium",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-SR26GN_P",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-FW520F",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Asus K54C",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
- },
- },
- {
- .callback = init_nvs_nosave,
- .ident = "Asus K54HR",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
- },
- },
- {},
-};
#endif /* CONFIG_SUSPEND */
#ifdef CONFIG_HIBERNATION
@@ -681,177 +715,6 @@ int acpi_suspend(u32 acpi_state)
return -EINVAL;
}
-#ifdef CONFIG_PM
-/**
- * acpi_pm_device_sleep_state - return preferred power state of ACPI device
- * in the system sleep state given by %acpi_target_sleep_state
- * @dev: device to examine; its driver model wakeup flags control
- * whether it should be able to wake up the system
- * @d_min_p: used to store the upper limit of allowed states range
- * @d_max_in: specify the lowest allowed states
- * Return value: preferred power state of the device on success, -ENODEV
- * (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
- *
- * Find the lowest power (highest number) ACPI device power state that
- * device @dev can be in while the system is in the sleep state represented
- * by %acpi_target_sleep_state. If @wake is nonzero, the device should be
- * able to wake up the system from this sleep state. If @d_min_p is set,
- * the highest power (lowest number) device power state of @dev allowed
- * in this system sleep state is stored at the location pointed to by it.
- *
- * The caller must ensure that @dev is valid before using this function.
- * The caller is also responsible for figuring out if the device is
- * supposed to be able to wake up the system and passing this information
- * via @wake.
- */
-
-int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
-{
- acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
- struct acpi_device *adev;
- char acpi_method[] = "_SxD";
- unsigned long long d_min, d_max;
-
- if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
- return -EINVAL;
- if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
- printk(KERN_DEBUG "ACPI handle has no context!\n");
- return -ENODEV;
- }
-
- acpi_method[2] = '0' + acpi_target_sleep_state;
- /*
- * If the sleep state is S0, the lowest limit from ACPI is D3,
- * but if the device has _S0W, we will use the value from _S0W
- * as the lowest limit from ACPI. Finally, we will constrain
- * the lowest limit with the specified one.
- */
- d_min = ACPI_STATE_D0;
- d_max = ACPI_STATE_D3;
-
- /*
- * If present, _SxD methods return the minimum D-state (highest power
- * state) we can use for the corresponding S-states. Otherwise, the
- * minimum D-state is D0 (ACPI 3.x).
- *
- * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
- * provided -- that's our fault recovery, we ignore retval.
- */
- if (acpi_target_sleep_state > ACPI_STATE_S0)
- acpi_evaluate_integer(handle, acpi_method, NULL, &d_min);
-
- /*
- * If _PRW says we can wake up the system from the target sleep state,
- * the D-state returned by _SxD is sufficient for that (we assume a
- * wakeup-aware driver if wake is set). Still, if _SxW exists
- * (ACPI 3.x), it should return the maximum (lowest power) D-state that
- * can wake the system. _S0W may be valid, too.
- */
- if (acpi_target_sleep_state == ACPI_STATE_S0 ||
- (device_may_wakeup(dev) && adev->wakeup.flags.valid &&
- adev->wakeup.sleep_state >= acpi_target_sleep_state)) {
- acpi_status status;
-
- acpi_method[3] = 'W';
- status = acpi_evaluate_integer(handle, acpi_method, NULL,
- &d_max);
- if (ACPI_FAILURE(status)) {
- if (acpi_target_sleep_state != ACPI_STATE_S0 ||
- status != AE_NOT_FOUND)
- d_max = d_min;
- } else if (d_max < d_min) {
- /* Warn the user of the broken DSDT */
- printk(KERN_WARNING "ACPI: Wrong value from %s\n",
- acpi_method);
- /* Sanitize it */
- d_min = d_max;
- }
- }
-
- if (d_max_in < d_min)
- return -EINVAL;
- if (d_min_p)
- *d_min_p = d_min;
- /* constrain d_max with specified lowest limit (max number) */
- if (d_max > d_max_in) {
- for (d_max = d_max_in; d_max > d_min; d_max--) {
- if (adev->power.states[d_max].flags.valid)
- break;
- }
- }
- return d_max;
-}
-EXPORT_SYMBOL(acpi_pm_device_sleep_state);
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_SLEEP
-/**
- * acpi_pm_device_run_wake - Enable/disable wake-up for given device.
- * @phys_dev: Device to enable/disable the platform to wake-up the system for.
- * @enable: Whether enable or disable the wake-up functionality.
- *
- * Find the ACPI device object corresponding to @pci_dev and try to
- * enable/disable the GPE associated with it.
- */
-int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
-{
- struct acpi_device *dev;
- acpi_handle handle;
-
- if (!device_run_wake(phys_dev))
- return -EINVAL;
-
- handle = DEVICE_ACPI_HANDLE(phys_dev);
- if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) {
- dev_dbg(phys_dev, "ACPI handle has no context in %s!\n",
- __func__);
- return -ENODEV;
- }
-
- if (enable) {
- acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
- acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
- } else {
- acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
- acpi_disable_wakeup_device_power(dev);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(acpi_pm_device_run_wake);
-
-/**
- * acpi_pm_device_sleep_wake - enable or disable the system wake-up
- * capability of given device
- * @dev: device to handle
- * @enable: 'true' - enable, 'false' - disable the wake-up capability
- */
-int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
-{
- acpi_handle handle;
- struct acpi_device *adev;
- int error;
-
- if (!device_can_wakeup(dev))
- return -EINVAL;
-
- handle = DEVICE_ACPI_HANDLE(dev);
- if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
- dev_dbg(dev, "ACPI handle has no context in %s!\n", __func__);
- return -ENODEV;
- }
-
- error = enable ?
- acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
- acpi_disable_wakeup_device_power(adev);
- if (!error)
- dev_info(dev, "wake-up capability %s by ACPI\n",
- enable ? "enabled" : "disabled");
-
- return error;
-}
-#endif /* CONFIG_PM_SLEEP */
-
static void acpi_power_off_prepare(void)
{
/* Prepare to power off the system */
@@ -873,13 +736,13 @@ int __init acpi_sleep_init(void)
u8 type_a, type_b;
#ifdef CONFIG_SUSPEND
int i = 0;
-
- dmi_check_system(acpisleep_dmi_table);
#endif
if (acpi_disabled)
return 0;
+ acpi_sleep_dmi_check();
+
sleep_states[ACPI_STATE_S0] = 1;
printk(KERN_INFO PREFIX "(supports S0");
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 7c3f98ba4afe..ea61ca9129cd 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -476,7 +476,7 @@ static void fixed_event_count(u32 event_number)
return;
}
-static void acpi_gbl_event_handler(u32 event_type, acpi_handle device,
+static void acpi_global_event_handler(u32 event_type, acpi_handle device,
u32 event_number, void *context)
{
if (event_type == ACPI_EVENT_TYPE_GPE)
@@ -638,7 +638,7 @@ void acpi_irq_stats_init(void)
if (all_counters == NULL)
goto fail;
- status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL);
+ status = acpi_install_global_event_handler(acpi_global_event_handler, NULL);
if (ACPI_FAILURE(status))
goto fail;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 804204d41999..6e8cc16b54c1 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -984,6 +984,38 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
}
}
+/*
+ * On some platforms, the AML code has dependency about
+ * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
+ * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
+ * /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
+ * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
+ * if _TMP has never been evaluated.
+ *
+ * As this dependency is totally transparent to OS, evaluate
+ * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
+ * _TMP, before they are actually used.
+ */
+static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
+{
+ acpi_handle handle = tz->device->handle;
+ unsigned long long value;
+ int i;
+
+ acpi_evaluate_integer(handle, "_CRT", NULL, &value);
+ acpi_evaluate_integer(handle, "_HOT", NULL, &value);
+ acpi_evaluate_integer(handle, "_PSV", NULL, &value);
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+ char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
+ acpi_status status;
+
+ status = acpi_evaluate_integer(handle, name, NULL, &value);
+ if (status == AE_NOT_FOUND)
+ break;
+ }
+ acpi_evaluate_integer(handle, "_TMP", NULL, &value);
+}
+
static int acpi_thermal_get_info(struct acpi_thermal *tz)
{
int result = 0;
@@ -992,6 +1024,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
if (!tz)
return -EINVAL;
+ acpi_thermal_aml_dependency_fix(tz);
+
/* Get trip points [_CRT, _PSV, etc.] (required) */
result = acpi_thermal_get_trip_points(tz);
if (result)
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 462f7e300363..744371304313 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -28,6 +28,8 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -457,3 +459,39 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
#endif
}
EXPORT_SYMBOL(acpi_evaluate_hotplug_ost);
+
+/**
+ * acpi_handle_printk: Print message with ACPI prefix and object path
+ *
+ * This function is called through acpi_handle_<level> macros and prints
+ * a message with ACPI prefix and object path. This function acquires
+ * the global namespace mutex to obtain an object path. In interrupt
+ * context, it shows the object path as <n/a>.
+ */
+void
+acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+ struct acpi_buffer buffer = {
+ .length = ACPI_ALLOCATE_BUFFER,
+ .pointer = NULL
+ };
+ const char *path;
+
+ va_start(args, fmt);
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ if (in_interrupt() ||
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
+ path = "<n/a>";
+ else
+ path = buffer.pointer;
+
+ printk("%sACPI: %s: %pV", level, path, &vaf);
+
+ va_end(args);
+ kfree(buffer.pointer);
+}
+EXPORT_SYMBOL(acpi_handle_printk);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 0230cb6cbb3a..ac9a69cd45f5 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -389,6 +389,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d)
return 0;
}
+static int video_ignore_initial_backlight(const struct dmi_system_id *d)
+{
+ use_bios_initial_backlight = 0;
+ return 0;
+}
+
static struct dmi_system_id video_dmi_table[] __initdata = {
/*
* Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -433,6 +439,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
},
},
+ {
+ .callback = video_ignore_initial_backlight,
+ .ident = "HP Folio 13-2000",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
+ },
+ },
{}
};
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index b728880ef10e..4ac2593234e7 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -156,6 +156,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "X360"),
},
},
+ {
+ .callback = video_detect_force_vendor,
+ .ident = "Asus UL30VT",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
+ },
+ },
{ },
};
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index b1ae48054dc5..b7078afddb74 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ahci_suspend(struct device *dev)
{
struct ahci_platform_data *pdata = dev_get_platdata(dev);
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index fd9ecf74e631..5b0ba3f20edc 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
struct acpi_device *acpi_dev;
struct acpi_device_power_state *states;
- if (ap->flags & ATA_FLAG_ACPI_SATA)
- ata_dev = &ap->link.device[sdev->channel];
- else
+ if (ap->flags & ATA_FLAG_ACPI_SATA) {
+ if (!sata_pmp_attached(ap))
+ ata_dev = &ap->link.device[sdev->id];
+ else
+ ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
+ }
+ else {
ata_dev = &ap->link.device[sdev->id];
+ }
*handle = ata_dev_acpi_handle(ata_dev);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3cc7096cfda7..f46fbd3bd3fb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
if (xfer_mode == t->mode)
return t;
+
+ WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
+ __func__, xfer_mode);
+
return NULL;
}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e3bda074fa12..a6df6a351d6e 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
{
sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1;
+ sdev->no_report_opcodes = 1;
+ sdev->no_write_same = 1;
/* Schedule policy is determined by ->qc_defer() callback and
* it needs to see every deferred qc. Set dev_blocked to 1 to
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index 26201ebef3ca..371fd2c698b7 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
return ret;
}
+ ret = clk_set_rate(acdev->clk, 166000000);
+ if (ret) {
+ dev_warn(acdev->host->dev, "clock set rate failed");
+ return ret;
+ }
+
spin_lock_irqsave(&acdev->host->lock, flags);
/* configure CF interface clock */
writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int arasan_cf_suspend(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 0d7c4c2cd26f..400bf1c3e982 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ahci_of_match);
-static int __init ahci_highbank_probe(struct platform_device *pdev)
+static int __devinit ahci_highbank_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int ahci_highbank_suspend(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 44a4256533e1..08608de87e4e 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
return 0;
}
+static int k2_sata_softreset(struct ata_link *link,
+ unsigned int *class, unsigned long deadline)
+{
+ u8 dmactl;
+ void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+ dmactl = readb(mmio + ATA_DMA_CMD);
+
+ /* Clear the start bit */
+ if (dmactl & ATA_DMA_START) {
+ dmactl &= ~ATA_DMA_START;
+ writeb(dmactl, mmio + ATA_DMA_CMD);
+ }
+
+ return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+ unsigned int *class, unsigned long deadline)
+{
+ u8 dmactl;
+ void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+ dmactl = readb(mmio + ATA_DMA_CMD);
+
+ /* Clear the start bit */
+ if (dmactl & ATA_DMA_START) {
+ dmactl &= ~ATA_DMA_START;
+ writeb(dmactl, mmio + ATA_DMA_CMD);
+ }
+
+ return sata_sff_hardreset(link, class, deadline);
+}
static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
{
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
static struct ata_port_operations k2_sata_ops = {
.inherits = &ata_bmdma_port_ops,
+ .softreset = k2_sata_softreset,
+ .hardreset = k2_sata_hardreset,
.sff_tf_load = k2_sata_tf_load,
.sff_tf_read = k2_sata_tf_read,
.sff_check_status = k2_stat_check_status,
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 89b30f32ba68..ff7bb8a42ed6 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -1961,6 +1961,7 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
res = loader_verify(lb, dev, rec);
if (res)
break;
+ rec = ihex_next_binrec(rec);
}
release_firmware(fw);
if (!res)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index b34b5cda5ae1..c8b453939da2 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -57,7 +57,7 @@ config DEVTMPFS_MOUNT
on the rootfs is completely empty.
config STANDALONE
- bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
+ bool "Select only drivers that don't need compile-time external firmware"
default y
help
Select this option if you don't have magic firmware for drivers that
@@ -185,7 +185,6 @@ config DMA_SHARED_BUFFER
bool
default n
select ANON_INODES
- depends on EXPERIMENTAL
help
This option enables the framework for buffer-sharing between
multiple drivers. A buffer is associated with a file using driver
@@ -193,8 +192,8 @@ config DMA_SHARED_BUFFER
driver.
config CMA
- bool "Contiguous Memory Allocator (EXPERIMENTAL)"
- depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL
+ bool "Contiguous Memory Allocator"
+ depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
select MIGRATION
select MEMORY_ISOLATION
help
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 8fc200b2e2c0..d78b204e65c1 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -158,7 +158,7 @@ attribute_container_add_device(struct device *dev,
ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
- dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+ dev_err(dev, "failed to allocate class container\n");
continue;
}
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 181ed2660b33..24eb07868344 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = {
static struct kset *bus_kset;
-
-#ifdef CONFIG_HOTPLUG
/* Manually detach a device from its associated driver. */
static ssize_t driver_unbind(struct device_driver *drv,
const char *buf, size_t count)
@@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
return -EINVAL;
return count;
}
-#endif
static struct device *next_device(struct klist_iter *i)
{
@@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus,
}
}
-#ifdef CONFIG_HOTPLUG
-/*
- * Thanks to drivers making their tables __devinit, we can't allow manual
- * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
- */
static int __must_check add_bind_files(struct device_driver *drv)
{
int ret;
@@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus)
bus_remove_file(bus, &bus_attr_drivers_autoprobe);
bus_remove_file(bus, &bus_attr_drivers_probe);
}
-#else
-static inline int add_bind_files(struct device_driver *drv) { return 0; }
-static inline void remove_bind_files(struct device_driver *drv) {}
-static inline int add_probe_files(struct bus_type *bus) { return 0; }
-static inline void remove_probe_files(struct bus_type *bus) {}
-#endif
static ssize_t driver_uevent_store(struct device_driver *drv,
const char *buf, size_t count)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index abea76c36a4b..417913974df8 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1180,7 +1180,6 @@ void device_del(struct device *dev)
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
- device_pm_remove(dev);
dpm_sysfs_remove(dev);
if (parent)
klist_del(&dev->p->knode_parent);
@@ -1205,6 +1204,7 @@ void device_del(struct device *dev)
device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
bus_remove_device(dev);
+ device_pm_remove(dev);
driver_deferred_probe_del(dev);
/* Notify the platform of the removal, in case they
@@ -1399,7 +1399,7 @@ struct root_device {
struct module *owner;
};
-inline struct root_device *to_root_device(struct device *d)
+static inline struct root_device *to_root_device(struct device *d)
{
return container_of(d, struct root_device, dev);
}
@@ -1840,10 +1840,12 @@ void device_shutdown(void)
pm_runtime_barrier(dev);
if (dev->bus && dev->bus->shutdown) {
- dev_dbg(dev, "shutdown\n");
+ if (initcall_debug)
+ dev_info(dev, "shutdown\n");
dev->bus->shutdown(dev);
} else if (dev->driver && dev->driver->shutdown) {
- dev_dbg(dev, "shutdown\n");
+ if (initcall_debug)
+ dev_info(dev, "shutdown\n");
dev->driver->shutdown(dev);
}
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 8731979d668a..668390664764 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -50,8 +50,8 @@ static void devres_log(struct device *dev, struct devres_node *node,
const char *op)
{
if (unlikely(log_devres))
- dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n",
- op, node, node->name, (unsigned long)node->size);
+ dev_err(dev, "DEVRES %3s %p %s (%lu bytes)\n",
+ op, node, node->name, (unsigned long)node->size);
}
#else /* CONFIG_DEBUG_DEVRES */
#define set_node_dbginfo(node, n, s) do {} while (0)
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 612afcc5a938..0ca54421ce97 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -57,8 +57,8 @@ struct cma *dma_contiguous_default_area;
* Users, who want to set the size of global CMA area for their system
* should use cma= kernel parameter.
*/
-static const unsigned long size_bytes = CMA_SIZE_MBYTES * SZ_1M;
-static long size_cmdline = -1;
+static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M;
+static phys_addr_t size_cmdline = -1;
static int __init early_cma(char *p)
{
@@ -70,7 +70,7 @@ early_param("cma", early_cma);
#ifdef CONFIG_CMA_SIZE_PERCENTAGE
-static unsigned long __init __maybe_unused cma_early_percent_memory(void)
+static phys_addr_t __init __maybe_unused cma_early_percent_memory(void)
{
struct memblock_region *reg;
unsigned long total_pages = 0;
@@ -88,7 +88,7 @@ static unsigned long __init __maybe_unused cma_early_percent_memory(void)
#else
-static inline __maybe_unused unsigned long cma_early_percent_memory(void)
+static inline __maybe_unused phys_addr_t cma_early_percent_memory(void)
{
return 0;
}
@@ -106,7 +106,7 @@ static inline __maybe_unused unsigned long cma_early_percent_memory(void)
*/
void __init dma_contiguous_reserve(phys_addr_t limit)
{
- unsigned long selected_size = 0;
+ phys_addr_t selected_size = 0;
pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit);
@@ -126,7 +126,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
if (selected_size) {
pr_debug("%s: reserving %ld MiB for global area\n", __func__,
- selected_size / SZ_1M);
+ (unsigned long)selected_size / SZ_1M);
dma_declare_contiguous(NULL, selected_size, 0, limit);
}
@@ -227,11 +227,11 @@ core_initcall(cma_init_reserved_areas);
* called by board specific code when early allocator (memblock or bootmem)
* is still activate.
*/
-int __init dma_declare_contiguous(struct device *dev, unsigned long size,
+int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
phys_addr_t base, phys_addr_t limit)
{
struct cma_reserved *r = &cma_reserved[cma_reserved_count];
- unsigned long alignment;
+ phys_addr_t alignment;
pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
(unsigned long)size, (unsigned long)base,
@@ -268,10 +268,6 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
if (!addr) {
base = -ENOMEM;
goto err;
- } else if (addr + size > ~(unsigned long)0) {
- memblock_free(addr, size);
- base = -EINVAL;
- goto err;
} else {
base = addr;
}
@@ -285,14 +281,14 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
r->size = size;
r->dev = dev;
cma_reserved_count++;
- pr_info("CMA: reserved %ld MiB at %08lx\n", size / SZ_1M,
+ pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
(unsigned long)base);
/* Architecture specific contiguous memory fixup. */
dma_contiguous_early_fixup(base, size);
return 0;
err:
- pr_err("CMA: failed to reserve %ld MiB\n", size / SZ_1M);
+ pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
return base;
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e489ed..d81460309182 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -143,7 +143,7 @@ struct fw_cache_entry {
};
struct firmware_priv {
- struct timer_list timeout;
+ struct delayed_work timeout_work;
bool nowait;
struct device dev;
struct firmware_buf *buf;
@@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref)
__func__, buf->fw_id, buf, buf->data,
(unsigned int)buf->size);
- spin_lock(&fwc->lock);
list_del(&buf->list);
spin_unlock(&fwc->lock);
@@ -263,19 +262,32 @@ static void __fw_free_buf(struct kref *ref)
static void fw_free_buf(struct firmware_buf *buf)
{
- kref_put(&buf->ref, __fw_free_buf);
+ struct firmware_cache *fwc = buf->fwc;
+ spin_lock(&fwc->lock);
+ if (!kref_put(&buf->ref, __fw_free_buf))
+ spin_unlock(&fwc->lock);
}
/* direct firmware loading support */
-static const char *fw_path[] = {
+static char fw_path_para[256];
+static const char * const fw_path[] = {
+ fw_path_para,
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
"/lib/firmware"
};
+/*
+ * Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH'
+ * from kernel command line because firmware_class is generally built in
+ * kernel instead of module.
+ */
+module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
+MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
+
/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
+static noinline_for_stack long fw_file_size(struct file *file)
{
struct kstat st;
if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
@@ -315,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
struct file *file;
+
+ /* skip the unset customized path */
+ if (!fw_path[i][0])
+ continue;
+
snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
file = filp_open(path, O_RDONLY, 0);
@@ -667,11 +684,18 @@ static struct bin_attribute firmware_attr_data = {
.write = firmware_data_write,
};
-static void firmware_class_timeout(u_long data)
+static void firmware_class_timeout_work(struct work_struct *work)
{
- struct firmware_priv *fw_priv = (struct firmware_priv *) data;
+ struct firmware_priv *fw_priv = container_of(work,
+ struct firmware_priv, timeout_work.work);
+ mutex_lock(&fw_lock);
+ if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) {
+ mutex_unlock(&fw_lock);
+ return;
+ }
fw_load_abort(fw_priv);
+ mutex_unlock(&fw_lock);
}
static struct firmware_priv *
@@ -690,8 +714,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
fw_priv->nowait = nowait;
fw_priv->fw = firmware;
- setup_timer(&fw_priv->timeout,
- firmware_class_timeout, (u_long) fw_priv);
+ INIT_DELAYED_WORK(&fw_priv->timeout_work,
+ firmware_class_timeout_work);
f_dev = &fw_priv->dev;
@@ -858,7 +882,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
dev_dbg(f_dev->parent, "firmware: direct-loading"
" firmware %s\n", buf->fw_id);
+ mutex_lock(&fw_lock);
set_bit(FW_STATUS_DONE, &buf->status);
+ mutex_unlock(&fw_lock);
complete_all(&buf->completion);
direct_load = 1;
goto handle_fw;
@@ -894,15 +920,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
dev_set_uevent_suppress(f_dev, false);
dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
if (timeout != MAX_SCHEDULE_TIMEOUT)
- mod_timer(&fw_priv->timeout,
- round_jiffies_up(jiffies + timeout));
+ schedule_delayed_work(&fw_priv->timeout_work, timeout);
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
}
wait_for_completion(&buf->completion);
- del_timer_sync(&fw_priv->timeout);
+ cancel_delayed_work_sync(&fw_priv->timeout_work);
handle_fw:
mutex_lock(&fw_lock);
@@ -963,6 +988,9 @@ err_put_dev:
* firmware image for this or any other device.
*
* Caller must hold the reference count of @device.
+ *
+ * The function can be called safely inside device's suspend and
+ * resume callback.
**/
int
request_firmware(const struct firmware **firmware_p, const char *name,
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 72c776f2a1f5..c0b8df38402b 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/idr.h>
+#include <linux/acpi.h>
#include "base.h"
#include "power/power.h"
@@ -44,7 +45,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
* be setup before the platform_notifier is called. So if a user needs to
* manipulate any relevant information in the pdev_archdata they can do:
*
- * platform_devic_alloc()
+ * platform_device_alloc()
* ... manipulate ...
* platform_device_add()
*
@@ -122,7 +123,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
/**
- * platform_get_irq - get an IRQ for a device
+ * platform_get_irq_byname - get an IRQ for a device by name
* @dev: platform device
* @name: IRQ name
*/
@@ -436,6 +437,7 @@ struct platform_device *platform_device_register_full(
goto err_alloc;
pdev->dev.parent = pdevinfo->parent;
+ ACPI_HANDLE_SET(&pdev->dev, pdevinfo->acpi_node.handle);
if (pdevinfo->dma_mask) {
/*
@@ -466,6 +468,7 @@ struct platform_device *platform_device_register_full(
ret = platform_device_add(pdev);
if (ret) {
err:
+ ACPI_HANDLE_SET(&pdev->dev, NULL);
kfree(pdev->dev.dma_mask);
err_alloc:
@@ -481,8 +484,16 @@ static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
+ int ret;
+
+ if (ACPI_HANDLE(_dev))
+ acpi_dev_pm_attach(_dev, true);
- return drv->probe(dev);
+ ret = drv->probe(dev);
+ if (ret && ACPI_HANDLE(_dev))
+ acpi_dev_pm_detach(_dev, true);
+
+ return ret;
}
static int platform_drv_probe_fail(struct device *_dev)
@@ -494,8 +505,13 @@ static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
+ int ret;
- return drv->remove(dev);
+ ret = drv->remove(dev);
+ if (ACPI_HANDLE(_dev))
+ acpi_dev_pm_detach(_dev, true);
+
+ return ret;
}
static void platform_drv_shutdown(struct device *_dev)
@@ -504,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev)
struct platform_device *dev = to_platform_device(_dev);
drv->shutdown(dev);
+ if (ACPI_HANDLE(_dev))
+ acpi_dev_pm_detach(_dev, true);
}
/**
@@ -709,6 +727,10 @@ static int platform_match(struct device *dev, struct device_driver *drv)
if (of_driver_match_device(dev, drv))
return 1;
+ /* Then try ACPI style match */
+ if (acpi_driver_match_device(dev, drv))
+ return 1;
+
/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index eb78e9640c4a..9d8fde709390 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -99,7 +99,7 @@ static void __pm_clk_remove(struct pm_clock_entry *ce)
if (ce->status < PCE_STATUS_ERROR) {
if (ce->status == PCE_STATUS_ENABLED)
- clk_disable(ce->clk);
+ clk_disable_unprepare(ce->clk);
if (ce->status >= PCE_STATUS_ACQUIRED)
clk_put(ce->clk);
@@ -396,7 +396,7 @@ static void enable_clock(struct device *dev, const char *con_id)
clk = clk_get(dev, con_id);
if (!IS_ERR(clk)) {
- clk_enable(clk);
+ clk_prepare_enable(clk);
clk_put(clk);
dev_info(dev, "Runtime PM disabled, clock forced on.\n");
}
@@ -413,7 +413,7 @@ static void disable_clock(struct device *dev, const char *con_id)
clk = clk_get(dev, con_id);
if (!IS_ERR(clk)) {
- clk_disable(clk);
+ clk_disable_unprepare(clk);
clk_put(clk);
dev_info(dev, "Runtime PM disabled, clock forced off.\n");
}
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 96b71b6536d6..acc3a8ded29d 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -470,10 +470,19 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
return -EBUSY;
not_suspended = 0;
- list_for_each_entry(pdd, &genpd->dev_list, list_node)
+ list_for_each_entry(pdd, &genpd->dev_list, list_node) {
+ enum pm_qos_flags_status stat;
+
+ stat = dev_pm_qos_flags(pdd->dev,
+ PM_QOS_FLAG_NO_POWER_OFF
+ | PM_QOS_FLAG_REMOTE_WAKEUP);
+ if (stat > PM_QOS_FLAGS_NONE)
+ return -EBUSY;
+
if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
|| pdd->dev->power.irq_safe))
not_suspended++;
+ }
if (not_suspended > genpd->in_progress)
return -EBUSY;
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index d9468642fc41..50b2831e027d 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -23,6 +23,7 @@
#include <linux/rcupdate.h>
#include <linux/opp.h>
#include <linux/of.h>
+#include <linux/export.h>
/*
* Internal data structure organization with the OPP layer library is as
@@ -65,6 +66,7 @@ struct opp {
unsigned long u_volt;
struct device_opp *dev_opp;
+ struct rcu_head head;
};
/**
@@ -160,6 +162,7 @@ unsigned long opp_get_voltage(struct opp *opp)
return v;
}
+EXPORT_SYMBOL(opp_get_voltage);
/**
* opp_get_freq() - Gets the frequency corresponding to an available opp
@@ -189,6 +192,7 @@ unsigned long opp_get_freq(struct opp *opp)
return f;
}
+EXPORT_SYMBOL(opp_get_freq);
/**
* opp_get_opp_count() - Get number of opps available in the opp list
@@ -221,6 +225,7 @@ int opp_get_opp_count(struct device *dev)
return count;
}
+EXPORT_SYMBOL(opp_get_opp_count);
/**
* opp_find_freq_exact() - search for an exact frequency
@@ -230,7 +235,10 @@ int opp_get_opp_count(struct device *dev)
*
* Searches for exact match in the opp list and returns pointer to the matching
* opp if found, else returns ERR_PTR in case of error and should be handled
- * using IS_ERR.
+ * using IS_ERR. Error return values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Note: available is a modifier for the search. if available=true, then the
* match is for exact matching frequency and is available in the stored OPP
@@ -249,7 +257,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
bool available)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp)) {
@@ -268,6 +276,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_exact);
/**
* opp_find_freq_ceil() - Search for an rounded ceil freq
@@ -278,7 +287,11 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
* for a device.
*
* Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. The reason for the same is that the opp pointer which is
@@ -289,7 +302,7 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
if (!dev || !freq) {
dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -298,7 +311,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp))
- return opp;
+ return ERR_CAST(dev_opp);
list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
if (temp_opp->available && temp_opp->rate >= *freq) {
@@ -310,6 +323,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_ceil);
/**
* opp_find_freq_floor() - Search for a rounded floor freq
@@ -320,7 +334,11 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
* for a device.
*
* Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. The reason for the same is that the opp pointer which is
@@ -331,7 +349,7 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
if (!dev || !freq) {
dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -340,7 +358,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp))
- return opp;
+ return ERR_CAST(dev_opp);
list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
if (temp_opp->available) {
@@ -356,6 +374,7 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_floor);
/**
* opp_add() - Add an OPP table from a table definitions
@@ -512,7 +531,7 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
list_replace_rcu(&opp->node, &new_opp->node);
mutex_unlock(&dev_opp_list_lock);
- synchronize_rcu();
+ kfree_rcu(opp, head);
/* Notify the change of the OPP availability */
if (availability_req)
@@ -522,13 +541,10 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
new_opp);
- /* clean up old opp */
- new_opp = opp;
- goto out;
+ return 0;
unlock:
mutex_unlock(&dev_opp_list_lock);
-out:
kfree(new_opp);
return r;
}
@@ -552,6 +568,7 @@ int opp_enable(struct device *dev, unsigned long freq)
{
return opp_set_availability(dev, freq, true);
}
+EXPORT_SYMBOL(opp_enable);
/**
* opp_disable() - Disable a specific OPP
@@ -573,6 +590,7 @@ int opp_disable(struct device *dev, unsigned long freq)
{
return opp_set_availability(dev, freq, false);
}
+EXPORT_SYMBOL(opp_disable);
#ifdef CONFIG_CPU_FREQ
/**
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 0dbfdf4419af..b16686a0a5a2 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -93,8 +93,10 @@ extern void dpm_sysfs_remove(struct device *dev);
extern void rpm_sysfs_remove(struct device *dev);
extern int wakeup_sysfs_add(struct device *dev);
extern void wakeup_sysfs_remove(struct device *dev);
-extern int pm_qos_sysfs_add(struct device *dev);
-extern void pm_qos_sysfs_remove(struct device *dev);
+extern int pm_qos_sysfs_add_latency(struct device *dev);
+extern void pm_qos_sysfs_remove_latency(struct device *dev);
+extern int pm_qos_sysfs_add_flags(struct device *dev);
+extern void pm_qos_sysfs_remove_flags(struct device *dev);
#else /* CONFIG_PM */
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 74a67e0019a2..ff46387f5308 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -40,6 +40,7 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/export.h>
+#include <linux/pm_runtime.h>
#include "power.h"
@@ -48,6 +49,50 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
/**
+ * __dev_pm_qos_flags - Check PM QoS flags for a given device.
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ *
+ * This routine must be called with dev->power.lock held.
+ */
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+ struct dev_pm_qos *qos = dev->power.qos;
+ struct pm_qos_flags *pqf;
+ s32 val;
+
+ if (!qos)
+ return PM_QOS_FLAGS_UNDEFINED;
+
+ pqf = &qos->flags;
+ if (list_empty(&pqf->list))
+ return PM_QOS_FLAGS_UNDEFINED;
+
+ val = pqf->effective_flags & mask;
+ if (val)
+ return (val == mask) ? PM_QOS_FLAGS_ALL : PM_QOS_FLAGS_SOME;
+
+ return PM_QOS_FLAGS_NONE;
+}
+
+/**
+ * dev_pm_qos_flags - Check PM QoS flags for a given device (locked).
+ * @dev: Device to check the PM QoS flags for.
+ * @mask: Flags to check against.
+ */
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
+{
+ unsigned long irqflags;
+ enum pm_qos_flags_status ret;
+
+ spin_lock_irqsave(&dev->power.lock, irqflags);
+ ret = __dev_pm_qos_flags(dev, mask);
+ spin_unlock_irqrestore(&dev->power.lock, irqflags);
+
+ return ret;
+}
+
+/**
* __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
* @dev: Device to get the PM QoS constraint value for.
*
@@ -55,9 +100,7 @@ static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
*/
s32 __dev_pm_qos_read_value(struct device *dev)
{
- struct pm_qos_constraints *c = dev->power.constraints;
-
- return c ? pm_qos_read_value(c) : 0;
+ return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0;
}
/**
@@ -76,30 +119,39 @@ s32 dev_pm_qos_read_value(struct device *dev)
return ret;
}
-/*
- * apply_constraint
- * @req: constraint request to apply
- * @action: action to perform add/update/remove, of type enum pm_qos_req_action
- * @value: defines the qos request
+/**
+ * apply_constraint - Add/modify/remove device PM QoS request.
+ * @req: Constraint request to apply
+ * @action: Action to perform (add/update/remove).
+ * @value: Value to assign to the QoS request.
*
* Internal function to update the constraints list using the PM QoS core
* code and if needed call the per-device and the global notification
* callbacks
*/
static int apply_constraint(struct dev_pm_qos_request *req,
- enum pm_qos_req_action action, int value)
+ enum pm_qos_req_action action, s32 value)
{
- int ret, curr_value;
-
- ret = pm_qos_update_target(req->dev->power.constraints,
- &req->node, action, value);
+ struct dev_pm_qos *qos = req->dev->power.qos;
+ int ret;
- if (ret) {
- /* Call the global callbacks if needed */
- curr_value = pm_qos_read_value(req->dev->power.constraints);
- blocking_notifier_call_chain(&dev_pm_notifiers,
- (unsigned long)curr_value,
- req);
+ switch(req->type) {
+ case DEV_PM_QOS_LATENCY:
+ ret = pm_qos_update_target(&qos->latency, &req->data.pnode,
+ action, value);
+ if (ret) {
+ value = pm_qos_read_value(&qos->latency);
+ blocking_notifier_call_chain(&dev_pm_notifiers,
+ (unsigned long)value,
+ req);
+ }
+ break;
+ case DEV_PM_QOS_FLAGS:
+ ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
+ action, value);
+ break;
+ default:
+ ret = -EINVAL;
}
return ret;
@@ -114,28 +166,32 @@ static int apply_constraint(struct dev_pm_qos_request *req,
*/
static int dev_pm_qos_constraints_allocate(struct device *dev)
{
+ struct dev_pm_qos *qos;
struct pm_qos_constraints *c;
struct blocking_notifier_head *n;
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
+ qos = kzalloc(sizeof(*qos), GFP_KERNEL);
+ if (!qos)
return -ENOMEM;
n = kzalloc(sizeof(*n), GFP_KERNEL);
if (!n) {
- kfree(c);
+ kfree(qos);
return -ENOMEM;
}
BLOCKING_INIT_NOTIFIER_HEAD(n);
+ c = &qos->latency;
plist_head_init(&c->list);
c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
c->type = PM_QOS_MIN;
c->notifiers = n;
+ INIT_LIST_HEAD(&qos->flags.list);
+
spin_lock_irq(&dev->power.lock);
- dev->power.constraints = c;
+ dev->power.qos = qos;
spin_unlock_irq(&dev->power.lock);
return 0;
@@ -151,7 +207,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
void dev_pm_qos_constraints_init(struct device *dev)
{
mutex_lock(&dev_pm_qos_mtx);
- dev->power.constraints = NULL;
+ dev->power.qos = NULL;
dev->power.power_state = PMSG_ON;
mutex_unlock(&dev_pm_qos_mtx);
}
@@ -164,24 +220,28 @@ void dev_pm_qos_constraints_init(struct device *dev)
*/
void dev_pm_qos_constraints_destroy(struct device *dev)
{
+ struct dev_pm_qos *qos;
struct dev_pm_qos_request *req, *tmp;
struct pm_qos_constraints *c;
+ struct pm_qos_flags *f;
/*
- * If the device's PM QoS resume latency limit has been exposed to user
- * space, it has to be hidden at this point.
+ * If the device's PM QoS resume latency limit or PM QoS flags have been
+ * exposed to user space, they have to be hidden at this point.
*/
dev_pm_qos_hide_latency_limit(dev);
+ dev_pm_qos_hide_flags(dev);
mutex_lock(&dev_pm_qos_mtx);
dev->power.power_state = PMSG_INVALID;
- c = dev->power.constraints;
- if (!c)
+ qos = dev->power.qos;
+ if (!qos)
goto out;
- /* Flush the constraints list for the device */
- plist_for_each_entry_safe(req, tmp, &c->list, node) {
+ /* Flush the constraints lists for the device. */
+ c = &qos->latency;
+ plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
/*
* Update constraints list and call the notification
* callbacks if needed
@@ -189,13 +249,18 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
}
+ f = &qos->flags;
+ list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
+ apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
+ }
spin_lock_irq(&dev->power.lock);
- dev->power.constraints = NULL;
+ dev->power.qos = NULL;
spin_unlock_irq(&dev->power.lock);
kfree(c->notifiers);
- kfree(c);
+ kfree(qos);
out:
mutex_unlock(&dev_pm_qos_mtx);
@@ -205,6 +270,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
* dev_pm_qos_add_request - inserts new qos request into the list
* @dev: target device for the constraint
* @req: pointer to a preallocated handle
+ * @type: type of the request
* @value: defines the qos request
*
* This function inserts a new entry in the device constraints list of
@@ -218,9 +284,12 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
* -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
* to allocate for data structures, -ENODEV if the device has just been removed
* from the system.
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
*/
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
- s32 value)
+ enum dev_pm_qos_req_type type, s32 value)
{
int ret = 0;
@@ -235,7 +304,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
mutex_lock(&dev_pm_qos_mtx);
- if (!dev->power.constraints) {
+ if (!dev->power.qos) {
if (dev->power.power_state.event == PM_EVENT_INVALID) {
/* The device has been removed from the system. */
req->dev = NULL;
@@ -251,8 +320,10 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
}
}
- if (!ret)
+ if (!ret) {
+ req->type = type;
ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
+ }
out:
mutex_unlock(&dev_pm_qos_mtx);
@@ -262,6 +333,37 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
/**
+ * __dev_pm_qos_update_request - Modify an existing device PM QoS request.
+ * @req : PM QoS request to modify.
+ * @new_value: New value to request.
+ */
+static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
+ s32 new_value)
+{
+ s32 curr_value;
+ int ret = 0;
+
+ if (!req->dev->power.qos)
+ return -ENODEV;
+
+ switch(req->type) {
+ case DEV_PM_QOS_LATENCY:
+ curr_value = req->data.pnode.prio;
+ break;
+ case DEV_PM_QOS_FLAGS:
+ curr_value = req->data.flr.flags;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (curr_value != new_value)
+ ret = apply_constraint(req, PM_QOS_UPDATE_REQ, new_value);
+
+ return ret;
+}
+
+/**
* dev_pm_qos_update_request - modifies an existing qos request
* @req : handle to list element holding a dev_pm_qos request to use
* @new_value: defines the qos request
@@ -275,11 +377,13 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
* 0 if the aggregated constraint value has not changed,
* -EINVAL in case of wrong parameters, -ENODEV if the device has been
* removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
*/
-int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
- s32 new_value)
+int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
{
- int ret = 0;
+ int ret;
if (!req) /*guard against callers passing in null */
return -EINVAL;
@@ -289,17 +393,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
return -EINVAL;
mutex_lock(&dev_pm_qos_mtx);
-
- if (req->dev->power.constraints) {
- if (new_value != req->node.prio)
- ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
- new_value);
- } else {
- /* Return if the device has been removed */
- ret = -ENODEV;
- }
-
+ ret = __dev_pm_qos_update_request(req, new_value);
mutex_unlock(&dev_pm_qos_mtx);
+
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
@@ -315,6 +411,9 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
* 0 if the aggregated constraint value has not changed,
* -EINVAL in case of wrong parameters, -ENODEV if the device has been
* removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
*/
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
{
@@ -329,7 +428,7 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
mutex_lock(&dev_pm_qos_mtx);
- if (req->dev->power.constraints) {
+ if (req->dev->power.qos) {
ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
@@ -362,13 +461,13 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
mutex_lock(&dev_pm_qos_mtx);
- if (!dev->power.constraints)
+ if (!dev->power.qos)
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);
+ dev->power.qos->latency.notifiers, notifier);
mutex_unlock(&dev_pm_qos_mtx);
return ret;
@@ -393,9 +492,9 @@ int dev_pm_qos_remove_notifier(struct device *dev,
mutex_lock(&dev_pm_qos_mtx);
/* Silently return if the constraints object is not present. */
- if (dev->power.constraints)
+ if (dev->power.qos)
retval = blocking_notifier_chain_unregister(
- dev->power.constraints->notifiers,
+ dev->power.qos->latency.notifiers,
notifier);
mutex_unlock(&dev_pm_qos_mtx);
@@ -449,9 +548,10 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
ancestor = ancestor->parent;
if (ancestor)
- error = dev_pm_qos_add_request(ancestor, req, value);
+ error = dev_pm_qos_add_request(ancestor, req,
+ DEV_PM_QOS_LATENCY, value);
- if (error)
+ if (error < 0)
req->dev = NULL;
return error;
@@ -459,10 +559,19 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
#ifdef CONFIG_PM_RUNTIME
-static void __dev_pm_qos_drop_user_request(struct device *dev)
+static void __dev_pm_qos_drop_user_request(struct device *dev,
+ enum dev_pm_qos_req_type type)
{
- dev_pm_qos_remove_request(dev->power.pq_req);
- dev->power.pq_req = NULL;
+ switch(type) {
+ case DEV_PM_QOS_LATENCY:
+ dev_pm_qos_remove_request(dev->power.qos->latency_req);
+ dev->power.qos->latency_req = NULL;
+ break;
+ case DEV_PM_QOS_FLAGS:
+ dev_pm_qos_remove_request(dev->power.qos->flags_req);
+ dev->power.qos->flags_req = NULL;
+ break;
+ }
}
/**
@@ -478,21 +587,21 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
if (!device_is_registered(dev) || value < 0)
return -EINVAL;
- if (dev->power.pq_req)
+ if (dev->power.qos && dev->power.qos->latency_req)
return -EEXIST;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
- ret = dev_pm_qos_add_request(dev, req, value);
+ ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
if (ret < 0)
return ret;
- dev->power.pq_req = req;
- ret = pm_qos_sysfs_add(dev);
+ dev->power.qos->latency_req = req;
+ ret = pm_qos_sysfs_add_latency(dev);
if (ret)
- __dev_pm_qos_drop_user_request(dev);
+ __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
return ret;
}
@@ -504,10 +613,92 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
*/
void dev_pm_qos_hide_latency_limit(struct device *dev)
{
- if (dev->power.pq_req) {
- pm_qos_sysfs_remove(dev);
- __dev_pm_qos_drop_user_request(dev);
+ if (dev->power.qos && dev->power.qos->latency_req) {
+ pm_qos_sysfs_remove_latency(dev);
+ __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
}
}
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
+
+/**
+ * dev_pm_qos_expose_flags - Expose PM QoS flags of a device to user space.
+ * @dev: Device whose PM QoS flags are to be exposed to user space.
+ * @val: Initial values of the flags.
+ */
+int dev_pm_qos_expose_flags(struct device *dev, s32 val)
+{
+ struct dev_pm_qos_request *req;
+ int ret;
+
+ if (!device_is_registered(dev))
+ return -EINVAL;
+
+ if (dev->power.qos && dev->power.qos->flags_req)
+ return -EEXIST;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ pm_runtime_get_sync(dev);
+ ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
+ if (ret < 0)
+ goto fail;
+
+ dev->power.qos->flags_req = req;
+ ret = pm_qos_sysfs_add_flags(dev);
+ if (ret)
+ __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+
+fail:
+ pm_runtime_put(dev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
+
+/**
+ * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
+ * @dev: Device whose PM QoS flags are to be hidden from user space.
+ */
+void dev_pm_qos_hide_flags(struct device *dev)
+{
+ if (dev->power.qos && dev->power.qos->flags_req) {
+ pm_qos_sysfs_remove_flags(dev);
+ pm_runtime_get_sync(dev);
+ __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+ pm_runtime_put(dev);
+ }
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
+
+/**
+ * dev_pm_qos_update_flags - Update PM QoS flags request owned by user space.
+ * @dev: Device to update the PM QoS flags request for.
+ * @mask: Flags to set/clear.
+ * @set: Whether to set or clear the flags (true means set).
+ */
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
+{
+ s32 value;
+ int ret;
+
+ if (!dev->power.qos || !dev->power.qos->flags_req)
+ return -EINVAL;
+
+ pm_runtime_get_sync(dev);
+ mutex_lock(&dev_pm_qos_mtx);
+
+ value = dev_pm_qos_requested_flags(dev);
+ if (set)
+ value |= mask;
+ else
+ value &= ~mask;
+
+ ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
+
+ mutex_unlock(&dev_pm_qos_mtx);
+ pm_runtime_put(dev);
+
+ return ret;
+}
#endif /* CONFIG_PM_RUNTIME */
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index b91dc6f1e914..50d16e3cb0a9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -221,7 +221,7 @@ static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show,
static ssize_t pm_qos_latency_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", dev->power.pq_req->node.prio);
+ return sprintf(buf, "%d\n", dev_pm_qos_requested_latency(dev));
}
static ssize_t pm_qos_latency_store(struct device *dev,
@@ -237,12 +237,66 @@ static ssize_t pm_qos_latency_store(struct device *dev,
if (value < 0)
return -EINVAL;
- ret = dev_pm_qos_update_request(dev->power.pq_req, value);
+ ret = dev_pm_qos_update_request(dev->power.qos->latency_req, value);
return ret < 0 ? ret : n;
}
static DEVICE_ATTR(pm_qos_resume_latency_us, 0644,
pm_qos_latency_show, pm_qos_latency_store);
+
+static ssize_t pm_qos_no_power_off_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+ & PM_QOS_FLAG_NO_POWER_OFF));
+}
+
+static ssize_t pm_qos_no_power_off_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ int ret;
+
+ if (kstrtoint(buf, 0, &ret))
+ return -EINVAL;
+
+ if (ret != 0 && ret != 1)
+ return -EINVAL;
+
+ ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_NO_POWER_OFF, ret);
+ return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_no_power_off, 0644,
+ pm_qos_no_power_off_show, pm_qos_no_power_off_store);
+
+static ssize_t pm_qos_remote_wakeup_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+ & PM_QOS_FLAG_REMOTE_WAKEUP));
+}
+
+static ssize_t pm_qos_remote_wakeup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ int ret;
+
+ if (kstrtoint(buf, 0, &ret))
+ return -EINVAL;
+
+ if (ret != 0 && ret != 1)
+ return -EINVAL;
+
+ ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP, ret);
+ return ret < 0 ? ret : n;
+}
+
+static DEVICE_ATTR(pm_qos_remote_wakeup, 0644,
+ pm_qos_remote_wakeup_show, pm_qos_remote_wakeup_store);
#endif /* CONFIG_PM_RUNTIME */
#ifdef CONFIG_PM_SLEEP
@@ -564,15 +618,27 @@ static struct attribute_group pm_runtime_attr_group = {
.attrs = runtime_attrs,
};
-static struct attribute *pm_qos_attrs[] = {
+static struct attribute *pm_qos_latency_attrs[] = {
#ifdef CONFIG_PM_RUNTIME
&dev_attr_pm_qos_resume_latency_us.attr,
#endif /* CONFIG_PM_RUNTIME */
NULL,
};
-static struct attribute_group pm_qos_attr_group = {
+static struct attribute_group pm_qos_latency_attr_group = {
.name = power_group_name,
- .attrs = pm_qos_attrs,
+ .attrs = pm_qos_latency_attrs,
+};
+
+static struct attribute *pm_qos_flags_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
+ &dev_attr_pm_qos_no_power_off.attr,
+ &dev_attr_pm_qos_remote_wakeup.attr,
+#endif /* CONFIG_PM_RUNTIME */
+ NULL,
+};
+static struct attribute_group pm_qos_flags_attr_group = {
+ .name = power_group_name,
+ .attrs = pm_qos_flags_attrs,
};
int dpm_sysfs_add(struct device *dev)
@@ -615,14 +681,24 @@ void wakeup_sysfs_remove(struct device *dev)
sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
}
-int pm_qos_sysfs_add(struct device *dev)
+int pm_qos_sysfs_add_latency(struct device *dev)
+{
+ return sysfs_merge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+void pm_qos_sysfs_remove_latency(struct device *dev)
+{
+ sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_attr_group);
+}
+
+int pm_qos_sysfs_add_flags(struct device *dev)
{
- return sysfs_merge_group(&dev->kobj, &pm_qos_attr_group);
+ return sysfs_merge_group(&dev->kobj, &pm_qos_flags_attr_group);
}
-void pm_qos_sysfs_remove(struct device *dev)
+void pm_qos_sysfs_remove_flags(struct device *dev)
{
- sysfs_unmerge_group(&dev->kobj, &pm_qos_attr_group);
+ sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
}
void rpm_sysfs_remove(struct device *dev)
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 3804a0af3ef1..9fe4f1865558 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
/* cf. http://lkml.org/lkml/2006/10/31/28 */
if (!fastfail)
- q->request_fn(q);
+ __blk_run_queue(q);
}
static void
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 1c49d7173966..2ddd64a9ffde 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4330,6 +4330,7 @@ out_unreg_region:
out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd");
out_put_disk:
+ destroy_workqueue(floppy_wq);
for (drive = 0; drive < N_DRIVE; drive++) {
if (!disks[drive])
break;
@@ -4340,7 +4341,6 @@ out_put_disk:
}
put_disk(disks[drive]);
}
- destroy_workqueue(floppy_wq);
return err;
}
@@ -4555,6 +4555,8 @@ static void __exit floppy_module_exit(void)
unregister_blkdev(FLOPPY_MAJOR, "fd");
platform_driver_unregister(&floppy_driver);
+ destroy_workqueue(floppy_wq);
+
for (drive = 0; drive < N_DRIVE; drive++) {
del_timer_sync(&motor_off_timer[drive]);
@@ -4578,7 +4580,6 @@ static void __exit floppy_module_exit(void)
cancel_delayed_work_sync(&fd_timeout);
cancel_delayed_work_sync(&fd_timer);
- destroy_workqueue(floppy_wq);
if (atomic_read(&usage_count))
floppy_release_irq_and_dma();
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index adc6f36564cf..9694dd99bbbc 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data)
struct mtip_cmd *command;
int tag, cmdto_cnt = 0;
unsigned int bit, group;
- unsigned int num_command_slots = port->dd->slot_groups * 32;
+ unsigned int num_command_slots;
unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
if (unlikely(!port))
@@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data)
}
/* clear the tag accumulator */
memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+ num_command_slots = port->dd->slot_groups * 32;
for (tag = 0; tag < num_command_slots; tag++) {
/*
@@ -2218,8 +2219,8 @@ static int exec_drive_taskfile(struct driver_data *dd,
fis.device);
/* check for erase mode support during secure erase.*/
- if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
- && (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+ if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf &&
+ (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
erasemode = 1;
}
@@ -2439,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
* return value
* None
*/
-static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
int nsect, int nents, int tag, void *callback,
void *data, int dir)
{
@@ -2447,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
struct mtip_port *port = dd->port;
struct mtip_cmd *command = &port->commands[tag];
int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ u64 start = sector;
/* Map the scatter list for DMA access */
nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
@@ -2465,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
fis->opts = 1 << 7;
fis->command =
(dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
- *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
- *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+ fis->lba_low = start & 0xFF;
+ fis->lba_mid = (start >> 8) & 0xFF;
+ fis->lba_hi = (start >> 16) & 0xFF;
+ fis->lba_low_ex = (start >> 24) & 0xFF;
+ fis->lba_mid_ex = (start >> 32) & 0xFF;
+ fis->lba_hi_ex = (start >> 40) & 0xFF;
fis->device = 1 << 6;
fis->features = nsect & 0xFF;
fis->features_ex = (nsect >> 8) & 0xFF;
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 5f4a917bd8bb..b1742640556a 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -34,7 +34,7 @@
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
/* check for erase mode support during secure erase */
-#define MTIP_SEC_ERASE_MODE 0x3
+#define MTIP_SEC_ERASE_MODE 0x2
/* # of times to retry timed out/failed IOs */
#define MTIP_MAX_RETRIES 2
@@ -155,14 +155,14 @@ enum {
MTIP_DDF_REBUILD_FAILED_BIT = 8,
};
-__packed struct smart_attr{
+struct smart_attr {
u8 attr_id;
u16 flags;
u8 cur;
u8 worst;
u32 data;
u8 res[3];
-};
+} __packed;
/* Register Frame Information Structure (FIS), host to device. */
struct host_to_dev_fis {
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index fd793519ea2b..478493543b32 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = {
};
-static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ali_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AL_M1541,
@@ -374,7 +374,7 @@ found:
return agp_add_bridge(bridge);
}
-static void __devexit agp_ali_remove(struct pci_dev *pdev)
+static void agp_ali_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index f7e88787af97..1b2101160e98 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
+static struct agp_device_ids amd_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006,
@@ -480,7 +480,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
+static void agp_amdk7_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 444f8b6ab411..061d46209b1a 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -579,7 +579,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
return 0;
}
-static void __devexit agp_amd64_remove(struct pci_dev *pdev)
+static void agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index dc30e2243494..ed0433576e74 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = {
};
-static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ati_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_ATI_RS100,
@@ -533,7 +533,7 @@ found:
return agp_add_bridge(bridge);
}
-static void __devexit agp_ati_remove(struct pci_dev *pdev)
+static void agp_ati_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index d607f53d8afc..55f3e33a309f 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -407,7 +407,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
+static void agp_efficeon_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 75b763cb3ea1..d328b662e50d 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -611,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
+static void agp_intel_i460_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index b130df0a1958..f3a8f52b5a00 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -819,7 +819,7 @@ found_gmch:
return err;
}
-static void __devexit agp_intel_remove(struct pci_dev *pdev)
+static void agp_intel_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index b9734a978186..66e0868000f4 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -388,7 +388,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
+static void agp_nvidia_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 3a5af2f9b015..a18791d7718a 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -327,7 +327,7 @@ static int __devinit agp_sgi_init(void)
return 0;
}
-static void __devexit agp_sgi_cleanup(void)
+static void agp_sgi_cleanup(void)
{
kfree(sgi_tioca_agp_bridges);
sgi_tioca_agp_bridges = NULL;
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 08704ae53956..93d1d31f9d0c 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -17,8 +17,8 @@
#define PCI_DEVICE_ID_SI_662 0x0662
#define PCI_DEVICE_ID_SI_671 0x0671
-static bool __devinitdata agp_sis_force_delay = 0;
-static int __devinitdata agp_sis_agp_spec = -1;
+static bool agp_sis_force_delay = 0;
+static int agp_sis_agp_spec = -1;
static int sis_fetch_size(void)
{
@@ -148,7 +148,7 @@ static struct agp_bridge_driver sis_driver = {
};
// chipsets that require the 'delay hack'
-static int sis_broken_chipsets[] __devinitdata = {
+static int sis_broken_chipsets[] = {
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_746,
0 // terminator
@@ -211,7 +211,7 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_sis_remove(struct pci_dev *pdev)
+static void agp_sis_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index f02f9b07fd4c..26020fb8d7a9 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -518,7 +518,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
+static void agp_serverworks_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a32c492baf5c..011967ad3eed 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = {
.needs_scratch_page = true,
};
-static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
+static struct agp_device_ids uninorth_agp_device_ids[] = {
{
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
.chipset_name = "UniNorth",
@@ -663,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_uninorth_remove(struct pci_dev *pdev)
+static void agp_uninorth_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 8bc384937401..6818595bb863 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids via_agp_device_ids[] __devinitdata =
+static struct agp_device_ids via_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_VIA_82C597_0,
@@ -485,7 +485,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_via_remove(struct pci_dev *pdev)
+static void agp_via_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index dfd7876f127c..fe6d4be48296 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -816,7 +816,7 @@ static unsigned long __hpet_calibrate(struct hpets *hpetp)
static unsigned long hpet_calibrate(struct hpets *hpetp)
{
- unsigned long ret = -1;
+ unsigned long ret = ~0UL;
unsigned long tmp;
/*
@@ -1001,6 +1001,9 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
irqp = &res->data.extended_irq;
for (i = 0; i < irqp->interrupt_count; i++) {
+ if (hdp->hd_nirqs >= HPET_MAX_TIMERS)
+ break;
+
irq = acpi_register_gsi(NULL, irqp->interrupts[i],
irqp->triggering, irqp->polarity);
if (irq < 0)
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index fbd9b2b850ef..c58ea9b80b1a 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -127,12 +127,12 @@ config HW_RANDOM_VIA
If unsure, say Y.
config HW_RANDOM_IXP4XX
- tristate "Intel IXP4xx NPU HW Random Number Generator support"
+ tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
depends on HW_RANDOM && ARCH_IXP4XX
default HW_RANDOM
---help---
- This driver provides kernel-side support for the Random
- Number Generator hardware found on the Intel IXP4xx NPU.
+ This driver provides kernel-side support for the Pseudo-Random
+ Number Generator hardware found on the Intel IXP45x/46x NPU.
To compile this driver as a module, choose M here: the
module will be called ixp4xx-rng.
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 731c9046cf7b..5a4a6e70478b 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -98,7 +98,7 @@ err_enable:
return ret;
}
-static int __devexit atmel_trng_remove(struct platform_device *pdev)
+static int atmel_trng_remove(struct platform_device *pdev)
{
struct atmel_trng *trng = platform_get_drvdata(pdev);
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c
index aec6a4277caa..ae95bcb18d4a 100644
--- a/drivers/char/hw_random/bcm63xx-rng.c
+++ b/drivers/char/hw_random/bcm63xx-rng.c
@@ -145,7 +145,7 @@ out:
return ret;
}
-static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
+static int bcm63xx_rng_remove(struct platform_device *pdev)
{
struct hwrng *rng = platform_get_drvdata(pdev);
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index 232ba9ce579c..bdc852ea7632 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -134,7 +134,7 @@ static int __devinit exynos_rng_probe(struct platform_device *pdev)
return hwrng_register(&exynos_rng->rng);
}
-static int __devexit exynos_rng_remove(struct platform_device *pdev)
+static int exynos_rng_remove(struct platform_device *pdev)
{
struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
index 263567f5f392..beec1627db3c 100644
--- a/drivers/char/hw_random/ixp4xx-rng.c
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -45,6 +45,9 @@ static int __init ixp4xx_rng_init(void)
void __iomem * rng_base;
int err;
+ if (!cpu_is_ixp46x()) /* includes IXP455 */
+ return -ENOSYS;
+
rng_base = ioremap(0x70002100, 4);
if (!rng_base)
return -ENOMEM;
@@ -68,5 +71,5 @@ module_init(ixp4xx_rng_init);
module_exit(ixp4xx_rng_exit);
MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index ebd48f0135da..d68a72a08b51 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -25,7 +25,7 @@
#define DRV_MODULE_VERSION "0.2"
#define DRV_MODULE_RELDATE "July 27, 2011"
-static char version[] __devinitdata =
+static char version[] =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@@ -719,7 +719,7 @@ out:
return err;
}
-static int __devexit n2rng_remove(struct platform_device *op)
+static int n2rng_remove(struct platform_device *op)
{
struct n2rng *np = dev_get_drvdata(&op->dev);
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index 3a632673aed5..a1f70407cc9e 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -122,7 +122,7 @@ static int __devinit rng_probe(struct platform_device *ofdev)
return err;
}
-static int __devexit rng_remove(struct platform_device *dev)
+static int rng_remove(struct platform_device *dev)
{
void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv;
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
index 97bd891422c7..d4b24c1dd48e 100644
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -151,7 +151,7 @@ err_enable:
return ret;
}
-static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
+static int picoxcell_trng_remove(struct platform_device *pdev)
{
hwrng_unregister(&picoxcell_trng);
clk_disable(rng_clk);
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index c51762c13031..af6506a69cd9 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -111,7 +111,7 @@ static int __devinit ppc4xx_rng_probe(struct platform_device *dev)
return err;
}
-static int __devexit ppc4xx_rng_remove(struct platform_device *dev)
+static int ppc4xx_rng_remove(struct platform_device *dev)
{
void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index f1a1618db1fb..3a1abc9417e4 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -130,7 +130,7 @@ failed:
return ret;
}
-static int __devexit timeriomem_rng_remove(struct platform_device *pdev)
+static int timeriomem_rng_remove(struct platform_device *pdev)
{
del_timer_sync(&timeriomem_rng_timer);
hwrng_unregister(&timeriomem_rng_ops);
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 5708299507d0..621f595f1a98 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -119,7 +119,7 @@ static int virtrng_probe(struct virtio_device *vdev)
return probe_common(vdev);
}
-static void __devexit virtrng_remove(struct virtio_device *vdev)
+static void virtrng_remove(struct virtio_device *vdev)
{
remove_common(vdev);
}
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 32a6c7e256bd..20ab5b3a8915 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1836,7 +1836,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
return rv;
}
-static int __devinit hardcode_find_bmc(void)
+static int hardcode_find_bmc(void)
{
int ret = -ENODEV;
int i;
@@ -2023,7 +2023,7 @@ struct SPMITable {
s8 spmi_id[1]; /* A '\0' terminated array starts here. */
};
-static int __devinit try_init_spmi(struct SPMITable *spmi)
+static int try_init_spmi(struct SPMITable *spmi)
{
struct smi_info *info;
@@ -2106,7 +2106,7 @@ static int __devinit try_init_spmi(struct SPMITable *spmi)
return 0;
}
-static void __devinit spmi_find_bmc(void)
+static void spmi_find_bmc(void)
{
acpi_status status;
struct SPMITable *spmi;
@@ -2128,7 +2128,7 @@ static void __devinit spmi_find_bmc(void)
}
}
-static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
+static int ipmi_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id)
{
struct acpi_device *acpi_dev;
@@ -2228,7 +2228,7 @@ err_free:
return -EINVAL;
}
-static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
+static void ipmi_pnp_remove(struct pnp_dev *dev)
{
struct smi_info *info = pnp_get_drvdata(dev);
@@ -2258,7 +2258,7 @@ struct dmi_ipmi_data {
u8 slave_addr;
};
-static int __devinit decode_dmi(const struct dmi_header *dm,
+static int decode_dmi(const struct dmi_header *dm,
struct dmi_ipmi_data *dmi)
{
const u8 *data = (const u8 *)dm;
@@ -2320,7 +2320,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
return 0;
}
-static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
+static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
{
struct smi_info *info;
@@ -2388,7 +2388,7 @@ static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
kfree(info);
}
-static void __devinit dmi_find_bmc(void)
+static void dmi_find_bmc(void)
{
const struct dmi_device *dev = NULL;
struct dmi_ipmi_data data;
@@ -2424,7 +2424,7 @@ static void ipmi_pci_cleanup(struct smi_info *info)
pci_disable_device(pdev);
}
-static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
+static int ipmi_pci_probe_regspacing(struct smi_info *info)
{
if (info->si_type == SI_KCS) {
unsigned char status;
@@ -2456,7 +2456,7 @@ static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
return DEFAULT_REGSPACING;
}
-static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
+static int ipmi_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int rv;
@@ -2529,7 +2529,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
return 0;
}
-static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
+static void ipmi_pci_remove(struct pci_dev *pdev)
{
struct smi_info *info = pci_get_drvdata(pdev);
cleanup_one_si(info);
@@ -2551,7 +2551,7 @@ static struct pci_driver ipmi_pci_driver = {
#endif /* CONFIG_PCI */
static struct of_device_id ipmi_match[];
-static int __devinit ipmi_probe(struct platform_device *dev)
+static int ipmi_probe(struct platform_device *dev)
{
#ifdef CONFIG_OF
const struct of_device_id *match;
@@ -2635,7 +2635,7 @@ static int __devinit ipmi_probe(struct platform_device *dev)
return 0;
}
-static int __devexit ipmi_remove(struct platform_device *dev)
+static int ipmi_remove(struct platform_device *dev)
{
#ifdef CONFIG_OF
cleanup_one_si(dev_get_drvdata(&dev->dev));
@@ -3047,7 +3047,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
}
}
-static __devinitdata struct ipmi_default_vals
+static struct ipmi_default_vals
{
int type;
int port;
@@ -3059,7 +3059,7 @@ static __devinitdata struct ipmi_default_vals
{ .port = 0 }
};
-static void __devinit default_find_bmc(void)
+static void default_find_bmc(void)
{
struct smi_info *info;
int i;
@@ -3359,7 +3359,7 @@ static int try_smi_init(struct smi_info *new_smi)
return rv;
}
-static int __devinit init_ipmi_si(void)
+static int init_ipmi_si(void)
{
int i;
char *str;
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index f74e892711dd..e5d3e3f7a49b 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
return 0;
}
-static const struct cx_device_id __devinitconst mbcs_id_table[] = {
+static const struct cx_device_id mbcs_id_table[] = {
{
.part_num = MBCS_PART_NUM,
.mfg_num = MBCS_MFG_NUM,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 0537903c985b..c6fa3bc2baa8 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -48,7 +48,7 @@ static inline unsigned long size_inside_page(unsigned long start,
}
#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t count)
+static inline int valid_phys_addr_range(phys_addr_t addr, size_t count)
{
return addr + count <= __pa(high_memory);
}
@@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
static ssize_t read_mem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- unsigned long p = *ppos;
+ phys_addr_t p = *ppos;
ssize_t read, sz;
char *ptr;
@@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
static ssize_t write_mem(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- unsigned long p = *ppos;
+ phys_addr_t p = *ppos;
ssize_t written, sz;
unsigned long copied;
void *ptr;
@@ -226,7 +226,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file,
*
*/
#ifdef pgprot_noncached
-static int uncached_access(struct file *file, unsigned long addr)
+static int uncached_access(struct file *file, phys_addr_t addr)
{
#if defined(CONFIG_IA64)
/*
@@ -258,7 +258,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot)
{
#ifdef pgprot_noncached
- unsigned long offset = pfn << PAGE_SHIFT;
+ phys_addr_t offset = pfn << PAGE_SHIFT;
if (uncached_access(file, offset))
return pgprot_noncached(vma_prot);
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index b304ec052501..3f79a9fb6b1b 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -345,8 +345,7 @@ static void __exit pc8736x_gpio_cleanup(void)
unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT);
release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
- platform_device_del(pdev);
- platform_device_put(pdev);
+ platform_device_unregister(pdev);
}
module_init(pc8736x_gpio_init);
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 6abdde4da2b7..588063ac9517 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -363,7 +363,7 @@ static struct miscdevice ps3flash_misc = {
.fops = &ps3flash_fops,
};
-static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
+static int ps3flash_probe(struct ps3_system_bus_device *_dev)
{
struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
struct ps3flash_private *priv;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 0bb207eaef2f..54a3a6d09819 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
static const struct file_operations raw_fops = {
.read = do_sync_read,
- .aio_read = blkdev_aio_read,
+ .aio_read = generic_file_aio_read,
.write = do_sync_write,
.aio_write = blkdev_aio_write,
.fsync = blkdev_fsync,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 9b4f0116ff21..d780295a1473 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1164,7 +1164,7 @@ static struct acpi_driver sonypi_acpi_driver = {
};
#endif
-static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
+static int sonypi_create_input_devices(struct platform_device *pdev)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
@@ -1225,7 +1225,7 @@ static int __devinit sonypi_create_input_devices(struct platform_device *pdev)
return error;
}
-static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
+static int sonypi_setup_ioports(struct sonypi_device *dev,
const struct sonypi_ioport_list *ioport_list)
{
/* try to detect if sony-laptop is being used and thus
@@ -1265,7 +1265,7 @@ static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
return -EBUSY;
}
-static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
+static int sonypi_setup_irq(struct sonypi_device *dev,
const struct sonypi_irq_list *irq_list)
{
while (irq_list->irq) {
@@ -1282,7 +1282,7 @@ static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
return -EBUSY;
}
-static void __devinit sonypi_display_info(void)
+static void sonypi_display_info(void)
{
printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
@@ -1304,7 +1304,7 @@ static void __devinit sonypi_display_info(void)
sonypi_misc_device.minor);
}
-static int __devinit sonypi_probe(struct platform_device *dev)
+static int sonypi_probe(struct platform_device *dev)
{
const struct sonypi_ioport_list *ioport_list;
const struct sonypi_irq_list *irq_list;
@@ -1428,7 +1428,7 @@ static int __devinit sonypi_probe(struct platform_device *dev)
return error;
}
-static int __devexit sonypi_remove(struct platform_device *dev)
+static int sonypi_remove(struct platform_device *dev)
{
sonypi_disable();
@@ -1491,7 +1491,7 @@ static struct platform_driver sonypi_driver = {
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
- .remove = __devexit_p(sonypi_remove),
+ .remove = sonypi_remove,
.shutdown = sonypi_shutdown,
};
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index ad264185eb10..34c63f85104d 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void)
vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
}
-static int __devinit tb0219_probe(struct platform_device *dev)
+static int tb0219_probe(struct platform_device *dev)
{
int retval;
@@ -318,7 +318,7 @@ static int __devinit tb0219_probe(struct platform_device *dev)
return 0;
}
-static int __devexit tb0219_remove(struct platform_device *dev)
+static int tb0219_remove(struct platform_device *dev)
{
_machine_restart = old_machine_restart;
@@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device;
static struct platform_driver tb0219_device_driver = {
.probe = tb0219_probe,
- .remove = __devexit_p(tb0219_remove),
+ .remove = tb0219_remove,
.driver = {
.name = "TB0219",
.owner = THIS_MODULE,
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 5a831aec9d4b..fb447bd0cb61 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -555,7 +555,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = {
.miscdev.fops = &tis_ops,
};
-static int __devinit tpm_tis_i2c_init(struct device *dev)
+static int tpm_tis_i2c_init(struct device *dev)
{
u32 vendor;
int rc = 0;
@@ -632,7 +632,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
-static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+static int tpm_tis_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int rc;
@@ -656,7 +656,7 @@ static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
return rc;
}
-static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
+static int tpm_tis_i2c_remove(struct i2c_client *client)
{
struct tpm_chip *chip = tpm_dev.chip;
release_locality(chip, chip->vendor.locality, 1);
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index efc4ab36a9d6..7da840d487d2 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -32,7 +32,7 @@
static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
-static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
+static struct vio_device_id tpm_ibmvtpm_device_table[] = {
{ "IBM,vtpm", "IBM,vtpm"},
{ "", "" }
};
@@ -267,7 +267,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
* Return value:
* 0
*/
-static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
+static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
int rc = 0;
@@ -602,7 +602,7 @@ static void ibmvtpm_tasklet(void *data)
* 0 - Success
* Non-zero - Failure
*/
-static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
const struct vio_device_id *id)
{
struct ibmvtpm_dev *ibmvtpm;
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 3251a44e8ceb..2b480c2960bb 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -415,7 +415,7 @@ static const struct pnp_device_id tpm_inf_pnp_tbl[] = {
MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl);
-static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev,
+static int tpm_inf_pnp_probe(struct pnp_dev *dev,
const struct pnp_device_id *dev_id)
{
int rc = 0;
@@ -594,7 +594,7 @@ err_last:
return rc;
}
-static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev)
+static void tpm_inf_pnp_remove(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);
@@ -655,7 +655,7 @@ static struct pnp_driver tpm_inf_pnp_driver = {
.probe = tpm_inf_pnp_probe,
.suspend = tpm_inf_pnp_suspend,
.resume = tpm_inf_pnp_resume,
- .remove = __devexit_p(tpm_inf_pnp_remove)
+ .remove = tpm_inf_pnp_remove
};
static int __init init_inf(void)
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 6bdf2671254f..ea31dafbcac2 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -729,7 +729,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
#endif
#ifdef CONFIG_PNP
-static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
+static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
const struct pnp_device_id *pnp_id)
{
resource_size_t start, len;
@@ -769,7 +769,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
return ret;
}
-static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+static struct pnp_device_id tpm_pnp_tbl[] = {
{"PNP0C31", 0}, /* TPM */
{"ATM1200", 0}, /* Atmel */
{"IFX0102", 0}, /* Infineon */
@@ -783,7 +783,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
};
MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
-static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
+static void tpm_tis_pnp_remove(struct pnp_dev *dev)
{
struct tpm_chip *chip = pnp_get_drvdata(dev);
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8ab9c3d4bf13..90493d4ead1f 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1846,7 +1846,7 @@ static void remove_controlq_data(struct ports_device *portdev)
* config space to see how many ports the host has spawned. We
* initialize each port found.
*/
-static int __devinit virtcons_probe(struct virtio_device *vdev)
+static int virtcons_probe(struct virtio_device *vdev)
{
struct ports_device *portdev;
int err;
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 2c5d15beea35..5224da5202d3 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -595,7 +595,7 @@ static const struct file_operations hwicap_fops = {
.llseek = noop_llseek,
};
-static int __devinit hwicap_setup(struct device *dev, int id,
+static int hwicap_setup(struct device *dev, int id,
const struct resource *regs_res,
const struct hwicap_driver_config *config,
const struct config_registers *config_regs)
@@ -717,7 +717,7 @@ static struct hwicap_driver_config fifo_icap_config = {
.reset = fifo_icap_reset,
};
-static int __devexit hwicap_remove(struct device *dev)
+static int hwicap_remove(struct device *dev)
{
struct hwicap_drvdata *drvdata;
@@ -740,7 +740,7 @@ static int __devexit hwicap_remove(struct device *dev)
}
#ifdef CONFIG_OF
-static int __devinit hwicap_of_probe(struct platform_device *op,
+static int hwicap_of_probe(struct platform_device *op,
const struct hwicap_driver_config *config)
{
struct resource res;
@@ -785,8 +785,8 @@ static inline int hwicap_of_probe(struct platform_device *op,
}
#endif /* CONFIG_OF */
-static const struct of_device_id __devinitconst hwicap_of_match[];
-static int __devinit hwicap_drv_probe(struct platform_device *pdev)
+static const struct of_device_id hwicap_of_match[];
+static int hwicap_drv_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct resource *res;
@@ -822,14 +822,14 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev)
&buffer_icap_config, regs);
}
-static int __devexit hwicap_drv_remove(struct platform_device *pdev)
+static int hwicap_drv_remove(struct platform_device *pdev)
{
return hwicap_remove(&pdev->dev);
}
#ifdef CONFIG_OF
/* Match table for device tree binding */
-static const struct of_device_id __devinitconst hwicap_of_match[] = {
+static const struct of_device_id hwicap_of_match[] = {
{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
{},
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index bace9e98f75d..823f62d900ba 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -42,10 +42,12 @@ config COMMON_CLK_WM831X
config COMMON_CLK_VERSATILE
bool "Clock driver for ARM Reference designs"
- depends on ARCH_INTEGRATOR || ARCH_REALVIEW
+ depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS
---help---
- Supports clocking on ARM Reference designs Integrator/AP,
- Integrator/CP, RealView PB1176, EB, PB11MP and PBX.
+ Supports clocking on ARM Reference designs:
+ - Integrator/AP and Integrator/CP
+ - RealView PB1176, EB, PB11MP and PBX
+ - Versatile Express
config COMMON_CLK_MAX77686
tristate "Clock driver for Maxim 77686 MFD"
@@ -53,4 +55,12 @@ config COMMON_CLK_MAX77686
---help---
This driver supports Maxim 77686 crystal oscillator clock.
+config CLK_TWL6040
+ tristate "External McPDM functional clock from twl6040"
+ depends on TWL6040_CORE
+ ---help---
+ Enable the external functional clock support on OMAP4+ platforms for
+ McPDM. McPDM module is using the external bit clock on the McPDM bus
+ as functional clock.
+
endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b91de00..2701235d5757 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
+obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
index 67ad16b20b81..b61ee2c5af84 100644
--- a/drivers/clk/clk-bcm2835.c
+++ b/drivers/clk/clk-bcm2835.c
@@ -33,17 +33,17 @@ void __init bcm2835_init_clocks(void)
clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
250000000);
- if (!clk)
+ if (IS_ERR(clk))
pr_err("sys_pclk not registered\n");
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
126000000);
- if (!clk)
+ if (IS_ERR(clk))
pr_err("apb_pclk not registered\n");
clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
3000000);
- if (!clk)
+ if (IS_ERR(clk))
pr_err("uart0_pclk not registered\n");
ret = clk_register_clkdev(clk, NULL, "20201000.uart");
if (ret)
@@ -51,7 +51,7 @@ void __init bcm2835_init_clocks(void)
clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
125000000);
- if (!clk)
+ if (IS_ERR(clk))
pr_err("uart1_pclk not registered\n");
ret = clk_register_clkdev(clk, NULL, "20215000.uart");
if (ret)
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index f5ec0eebd4d7..af78ed6b67ef 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -97,7 +97,7 @@ void __init of_fixed_clk_setup(struct device_node *node)
of_property_read_string(node, "clock-output-names", &clk_name);
clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
- if (clk)
+ if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
index ac5f5434cb9a..d098f72e1d5f 100644
--- a/drivers/clk/clk-max77686.c
+++ b/drivers/clk/clk-max77686.c
@@ -143,7 +143,7 @@ static int max77686_clk_register(struct device *dev,
return 0;
}
-static __devinit int max77686_clk_probe(struct platform_device *pdev)
+static int max77686_clk_probe(struct platform_device *pdev)
{
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77686_clk **max77686_clks;
@@ -199,7 +199,7 @@ out:
return ret;
}
-static int __devexit max77686_clk_remove(struct platform_device *pdev)
+static int max77686_clk_remove(struct platform_device *pdev)
{
struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
int i;
@@ -223,7 +223,7 @@ static struct platform_driver max77686_clk_driver = {
.owner = THIS_MODULE,
},
.probe = max77686_clk_probe,
- .remove = __devexit_p(max77686_clk_remove),
+ .remove = max77686_clk_remove,
.id_table = max77686_clk_id,
};
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
index 517874fa6858..a203ecccdc4f 100644
--- a/drivers/clk/clk-prima2.c
+++ b/drivers/clk/clk-prima2.c
@@ -1054,118 +1054,118 @@ void __init sirfsoc_of_clk_init(void)
/* These are always available (RTC and 26MHz OSC)*/
clk = clk_register_fixed_rate(NULL, "rtc", NULL,
CLK_IS_ROOT, 32768);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register_fixed_rate(NULL, "osc", NULL,
CLK_IS_ROOT, 26000000);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_pll1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_pll2.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_pll3.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_mem.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_sys.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_security.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b8030000.security");
clk = clk_register(NULL, &clk_dsp.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_gps.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "a8010000.gps");
clk = clk_register(NULL, &clk_mf.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_io.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "io");
clk = clk_register(NULL, &clk_cpu.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "cpu");
clk = clk_register(NULL, &clk_uart0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0050000.uart");
clk = clk_register(NULL, &clk_uart1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0060000.uart");
clk = clk_register(NULL, &clk_uart2.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0070000.uart");
clk = clk_register(NULL, &clk_tsc.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0110000.tsc");
clk = clk_register(NULL, &clk_i2c0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00e0000.i2c");
clk = clk_register(NULL, &clk_i2c1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00f0000.i2c");
clk = clk_register(NULL, &clk_spi0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00d0000.spi");
clk = clk_register(NULL, &clk_spi1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0170000.spi");
clk = clk_register(NULL, &clk_pwmc.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0130000.pwm");
clk = clk_register(NULL, &clk_efuse.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0140000.efusesys");
clk = clk_register(NULL, &clk_pulse.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0150000.pulsec");
clk = clk_register(NULL, &clk_dmac0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
clk = clk_register(NULL, &clk_dmac1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
clk = clk_register(NULL, &clk_nand.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0030000.nand");
clk = clk_register(NULL, &clk_audio.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0040000.audio");
clk = clk_register(NULL, &clk_usp0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0080000.usp");
clk = clk_register(NULL, &clk_usp1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b0090000.usp");
clk = clk_register(NULL, &clk_usp2.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00a0000.usp");
clk = clk_register(NULL, &clk_vip.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00c0000.vip");
clk = clk_register(NULL, &clk_gfx.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "98000000.graphics");
clk = clk_register(NULL, &clk_mm.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "a0000000.multimedia");
clk = clk_register(NULL, &clk_lcd.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "90010000.display");
clk = clk_register(NULL, &clk_vpp.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "90020000.vpp");
clk = clk_register(NULL, &clk_mmc01.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_mmc23.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_mmc45.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &usb_pll_clk_hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk = clk_register(NULL, &clk_usb0.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00e0000.usb");
clk = clk_register(NULL, &clk_usb1.hw);
- BUG_ON(!clk);
+ BUG_ON(IS_ERR(clk));
clk_register_clkdev(clk, NULL, "b00f0000.usb");
}
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
new file mode 100644
index 000000000000..bc1e713e7b9c
--- /dev/null
+++ b/drivers/clk/clk-twl6040.c
@@ -0,0 +1,126 @@
+/*
+* TWL6040 clock module driver for OMAP4 McPDM functional clock
+*
+* Copyright (C) 2012 Texas Instruments Inc.
+* Peter Ujfalusi <peter.ujfalusi@ti.com>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*
+*/
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/clk-provider.h>
+
+struct twl6040_clk {
+ struct twl6040 *twl6040;
+ struct device *dev;
+ struct clk_hw mcpdm_fclk;
+ struct clk *clk;
+ int enabled;
+};
+
+static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
+{
+ struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+ mcpdm_fclk);
+ return twl6040_clk->enabled;
+}
+
+static int twl6040_bitclk_prepare(struct clk_hw *hw)
+{
+ struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+ mcpdm_fclk);
+ int ret;
+
+ ret = twl6040_power(twl6040_clk->twl6040, 1);
+ if (!ret)
+ twl6040_clk->enabled = 1;
+
+ return ret;
+}
+
+static void twl6040_bitclk_unprepare(struct clk_hw *hw)
+{
+ struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+ mcpdm_fclk);
+ int ret;
+
+ ret = twl6040_power(twl6040_clk->twl6040, 0);
+ if (!ret)
+ twl6040_clk->enabled = 0;
+}
+
+static const struct clk_ops twl6040_mcpdm_ops = {
+ .is_enabled = twl6040_bitclk_is_enabled,
+ .prepare = twl6040_bitclk_prepare,
+ .unprepare = twl6040_bitclk_unprepare,
+};
+
+static struct clk_init_data wm831x_clkout_init = {
+ .name = "mcpdm_fclk",
+ .ops = &twl6040_mcpdm_ops,
+ .flags = CLK_IS_ROOT,
+};
+
+static int __devinit twl6040_clk_probe(struct platform_device *pdev)
+{
+ struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
+ struct twl6040_clk *clkdata;
+
+ clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
+ if (!clkdata)
+ return -ENOMEM;
+
+ clkdata->dev = &pdev->dev;
+ clkdata->twl6040 = twl6040;
+
+ clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
+ clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+ if (IS_ERR(clkdata->clk))
+ return PTR_ERR(clkdata->clk);
+
+ dev_set_drvdata(&pdev->dev, clkdata);
+
+ return 0;
+}
+
+static int __devexit twl6040_clk_remove(struct platform_device *pdev)
+{
+ struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+ clk_unregister(clkdata->clk);
+
+ return 0;
+}
+
+static struct platform_driver twl6040_clk_driver = {
+ .driver = {
+ .name = "twl6040-clk",
+ .owner = THIS_MODULE,
+ },
+ .probe = twl6040_clk_probe,
+ .remove = __devexit_p(twl6040_clk_remove),
+};
+
+module_platform_driver(twl6040_clk_driver);
+
+MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_ALIAS("platform:twl6040-clk");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
index a885600f5270..fe25570874d6 100644
--- a/drivers/clk/clk-vt8500.c
+++ b/drivers/clk/clk-vt8500.c
@@ -120,8 +120,17 @@ static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,
static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
+ struct clk_device *cdev = to_clk_device(hw);
u32 divisor = *prate / rate;
+ /*
+ * If this is a request for SDMMC we have to adjust the divisor
+ * when >31 to use the fixed predivisor
+ */
+ if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+ divisor = 64 * ((divisor / 64) + 1);
+ }
+
return *prate / divisor;
}
@@ -135,6 +144,15 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
if (divisor == cdev->div_mask + 1)
divisor = 0;
+ /* SDMMC mask may need to be corrected before testing if its valid */
+ if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+ /*
+ * Bit 5 is a fixed /64 predivisor. If the requested divisor
+ * is >31 then correct for the fixed divisor being required.
+ */
+ divisor = 0x20 + (divisor / 64);
+ }
+
if (divisor > cdev->div_mask) {
pr_err("%s: invalid divisor for clock\n", __func__);
return -EINVAL;
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index e7b7765e85f3..16ed06808554 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -350,7 +350,7 @@ static struct clk_init_data wm831x_clkout_init = {
.flags = CLK_SET_RATE_PARENT,
};
-static __devinit int wm831x_clk_probe(struct platform_device *pdev)
+static int wm831x_clk_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_clk *clkdata;
@@ -370,49 +370,33 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
clkdata->xtal_hw.init = &wm831x_xtal_init;
- clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
- if (!clkdata->xtal)
- return -EINVAL;
+ clkdata->xtal = devm_clk_register(&pdev->dev, &clkdata->xtal_hw);
+ if (IS_ERR(clkdata->xtal))
+ return PTR_ERR(clkdata->xtal);
clkdata->fll_hw.init = &wm831x_fll_init;
- clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
- if (!clkdata->fll) {
- ret = -EINVAL;
- goto err_xtal;
- }
+ clkdata->fll = devm_clk_register(&pdev->dev, &clkdata->fll_hw);
+ if (IS_ERR(clkdata->fll))
+ return PTR_ERR(clkdata->fll);
clkdata->clkout_hw.init = &wm831x_clkout_init;
- clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
- if (!clkdata->clkout) {
- ret = -EINVAL;
- goto err_fll;
- }
+ clkdata->clkout = devm_clk_register(&pdev->dev, &clkdata->clkout_hw);
+ if (IS_ERR(clkdata->clkout))
+ return PTR_ERR(clkdata->clkout);
dev_set_drvdata(&pdev->dev, clkdata);
return 0;
-
-err_fll:
- clk_unregister(clkdata->fll);
-err_xtal:
- clk_unregister(clkdata->xtal);
- return ret;
}
-static int __devexit wm831x_clk_remove(struct platform_device *pdev)
+static int wm831x_clk_remove(struct platform_device *pdev)
{
- struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
-
- clk_unregister(clkdata->clkout);
- clk_unregister(clkdata->fll);
- clk_unregister(clkdata->xtal);
-
return 0;
}
static struct platform_driver wm831x_clk_driver = {
.probe = wm831x_clk_probe,
- .remove = __devexit_p(wm831x_clk_remove),
+ .remove = wm831x_clk_remove,
.driver = {
.name = "wm831x-clk",
.owner = THIS_MODULE,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 56e4495ebeb1..251e45d6024d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/device.h>
static DEFINE_SPINLOCK(enable_lock);
static DEFINE_MUTEX(prepare_lock);
@@ -218,8 +219,17 @@ static void clk_disable_unused_subtree(struct clk *clk)
if (clk->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
- if (__clk_is_enabled(clk) && clk->ops->disable)
- clk->ops->disable(clk->hw);
+ /*
+ * some gate clocks have special needs during the disable-unused
+ * sequence. call .disable_unused if available, otherwise fall
+ * back to .disable
+ */
+ if (__clk_is_enabled(clk)) {
+ if (clk->ops->disable_unused)
+ clk->ops->disable_unused(clk->hw);
+ else if (clk->ops->disable)
+ clk->ops->disable(clk->hw);
+ }
unlock_out:
spin_unlock_irqrestore(&enable_lock, flags);
@@ -261,7 +271,7 @@ inline struct clk_hw *__clk_get_hw(struct clk *clk)
inline u8 __clk_get_num_parents(struct clk *clk)
{
- return !clk ? -EINVAL : clk->num_parents;
+ return !clk ? 0 : clk->num_parents;
}
inline struct clk *__clk_get_parent(struct clk *clk)
@@ -269,14 +279,14 @@ inline struct clk *__clk_get_parent(struct clk *clk)
return !clk ? NULL : clk->parent;
}
-inline int __clk_get_enable_count(struct clk *clk)
+inline unsigned int __clk_get_enable_count(struct clk *clk)
{
- return !clk ? -EINVAL : clk->enable_count;
+ return !clk ? 0 : clk->enable_count;
}
-inline int __clk_get_prepare_count(struct clk *clk)
+inline unsigned int __clk_get_prepare_count(struct clk *clk)
{
- return !clk ? -EINVAL : clk->prepare_count;
+ return !clk ? 0 : clk->prepare_count;
}
unsigned long __clk_get_rate(struct clk *clk)
@@ -302,15 +312,15 @@ out:
inline unsigned long __clk_get_flags(struct clk *clk)
{
- return !clk ? -EINVAL : clk->flags;
+ return !clk ? 0 : clk->flags;
}
-int __clk_is_enabled(struct clk *clk)
+bool __clk_is_enabled(struct clk *clk)
{
int ret;
if (!clk)
- return -EINVAL;
+ return false;
/*
* .is_enabled is only mandatory for clocks that gate
@@ -323,7 +333,7 @@ int __clk_is_enabled(struct clk *clk)
ret = clk->ops->is_enabled(clk->hw);
out:
- return ret;
+ return !!ret;
}
static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
@@ -568,7 +578,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
unsigned long parent_rate = 0;
if (!clk)
- return -EINVAL;
+ return 0;
if (!clk->ops->round_rate) {
if (clk->flags & CLK_SET_RATE_PARENT)
@@ -1297,12 +1307,20 @@ int __clk_init(struct device *dev, struct clk *clk)
* walk the list of orphan clocks and reparent any that are children of
* this clock
*/
- hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
+ hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) {
+ if (orphan->ops->get_parent) {
+ i = orphan->ops->get_parent(orphan->hw);
+ if (!strcmp(clk->name, orphan->parent_names[i]))
+ __clk_reparent(orphan, clk);
+ continue;
+ }
+
for (i = 0; i < orphan->num_parents; i++)
if (!strcmp(clk->name, orphan->parent_names[i])) {
__clk_reparent(orphan, clk);
break;
}
+ }
/*
* optional platform-specific magic
@@ -1361,28 +1379,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
}
EXPORT_SYMBOL_GPL(__clk_register);
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes. It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API. In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
{
int i, ret;
- struct clk *clk;
-
- clk = kzalloc(sizeof(*clk), GFP_KERNEL);
- if (!clk) {
- pr_err("%s: could not allocate clk\n", __func__);
- ret = -ENOMEM;
- goto fail_out;
- }
clk->name = kstrdup(hw->init->name, GFP_KERNEL);
if (!clk->name) {
@@ -1420,7 +1419,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
ret = __clk_init(dev, clk);
if (!ret)
- return clk;
+ return 0;
fail_parent_names_copy:
while (--i >= 0)
@@ -1429,6 +1428,36 @@ fail_parent_names_copy:
fail_parent_names:
kfree(clk->name);
fail_name:
+ return ret;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes. It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API. In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+ int ret;
+ struct clk *clk;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk) {
+ pr_err("%s: could not allocate clk\n", __func__);
+ ret = -ENOMEM;
+ goto fail_out;
+ }
+
+ ret = _clk_register(dev, hw, clk);
+ if (!ret)
+ return clk;
+
kfree(clk);
fail_out:
return ERR_PTR(ret);
@@ -1444,6 +1473,63 @@ EXPORT_SYMBOL_GPL(clk_register);
void clk_unregister(struct clk *clk) {}
EXPORT_SYMBOL_GPL(clk_unregister);
+static void devm_clk_release(struct device *dev, void *res)
+{
+ clk_unregister(res);
+}
+
+/**
+ * devm_clk_register - resource managed clk_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_register(). Clocks returned from this function are
+ * automatically clk_unregister()ed on driver detach. See clk_register() for
+ * more information.
+ */
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ ret = _clk_register(dev, hw, clk);
+ if (!ret) {
+ devres_add(dev, clk);
+ } else {
+ devres_free(clk);
+ clk = ERR_PTR(ret);
+ }
+
+ return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_register);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+ struct clk *c = res;
+ if (WARN_ON(!c))
+ return 0;
+ return c == data;
+}
+
+/**
+ * devm_clk_unregister - resource managed clk_unregister()
+ * @clk: clock to unregister
+ *
+ * Deallocate a clock allocated with devm_clk_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+ WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
+}
+EXPORT_SYMBOL_GPL(devm_clk_unregister);
+
/*** clk rate change notifiers ***/
/**
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index f00dffb9ad60..8dd476e2a9c5 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -85,7 +85,7 @@ enum imx23_clk {
cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll,
emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div,
clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif,
- lcdif, etm, usb, usb_pwr,
+ lcdif, etm, usb, usb_phy,
clk_max
};
@@ -143,8 +143,8 @@ int __init mx23_clocks_init(void)
clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31);
clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31);
clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31);
- clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2);
- clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
+ clks[usb] = mxs_clk_gate("usb", "usb_phy", DIGCTRL, 2);
+ clks[usb_phy] = clk_register_gate(NULL, "usb_phy", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
for (i = 0; i < ARRAY_SIZE(clks); i++)
if (IS_ERR(clks[i])) {
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 42978f1b4bd2..db3af0874121 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -140,7 +140,7 @@ enum imx28_clk {
emi_xtal, lcdif_div, etm_div, ptp, saif0_div, saif1_div,
clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0,
ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm,
- fec, can0, can1, usb0, usb1, usb0_pwr, usb1_pwr, enet_out,
+ fec, can0, can1, usb0, usb1, usb0_phy, usb1_phy, enet_out,
clk_max
};
@@ -218,10 +218,10 @@ int __init mx28_clocks_init(void)
clks[fec] = mxs_clk_gate("fec", "hbus", ENET, 30);
clks[can0] = mxs_clk_gate("can0", "ref_xtal", FLEXCAN, 30);
clks[can1] = mxs_clk_gate("can1", "ref_xtal", FLEXCAN, 28);
- clks[usb0] = mxs_clk_gate("usb0", "usb0_pwr", DIGCTRL, 2);
- clks[usb1] = mxs_clk_gate("usb1", "usb1_pwr", DIGCTRL, 16);
- clks[usb0_pwr] = clk_register_gate(NULL, "usb0_pwr", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
- clks[usb1_pwr] = clk_register_gate(NULL, "usb1_pwr", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
+ clks[usb0] = mxs_clk_gate("usb0", "usb0_phy", DIGCTRL, 2);
+ clks[usb1] = mxs_clk_gate("usb1", "usb1_phy", DIGCTRL, 16);
+ clks[usb0_phy] = clk_register_gate(NULL, "usb0_phy", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
+ clks[usb1_phy] = clk_register_gate(NULL, "usb1_phy", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
clks[enet_out] = clk_register_gate(NULL, "enet_out", "pll2", 0, ENET, 18, 0, &mxs_lock);
for (i = 0; i < ARRAY_SIZE(clks); i++)
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c
index 6756e7c3bc07..bdfb4421c643 100644
--- a/drivers/clk/spear/clk-aux-synth.c
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -179,7 +179,8 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
if (gate_name) {
struct clk *tgate_clk;
- tgate_clk = clk_register_gate(NULL, gate_name, aux_name, 0, reg,
+ tgate_clk = clk_register_gate(NULL, gate_name, aux_name,
+ CLK_SET_RATE_PARENT, reg,
aux->masks->enable_bit, 0, lock);
if (IS_ERR_OR_NULL(tgate_clk))
goto free_aux;
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
index 5f1b6badeb15..1b9b65bca51e 100644
--- a/drivers/clk/spear/clk-vco-pll.c
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -147,7 +147,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
struct clk_pll *pll = to_clk_pll(hw);
struct pll_rate_tbl *rtbl = pll->vco->rtbl;
unsigned long flags = 0, val;
- int i;
+ int uninitialized_var(i);
clk_pll_round_rate_index(hw, drate, NULL, &i);
diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c
index 7cd63788d546..628b6d5ed3d9 100644
--- a/drivers/clk/spear/clk.c
+++ b/drivers/clk/spear/clk.c
@@ -32,5 +32,8 @@ long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
}
}
+ if ((*index) == rtbl_cnt)
+ (*index)--;
+
return rate;
}
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 0fcec2aae19c..147e25f00405 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -313,6 +313,20 @@ static struct aux_clk_masks i2s_sclk_masks = {
/* i2s prs1 aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl i2s_prs1_rtbl[] = {
/* For parent clk = 49.152 MHz */
+ {.xscale = 1, .yscale = 12, .eq = 0}, /* 2.048 MHz, smp freq = 8Khz */
+ {.xscale = 11, .yscale = 96, .eq = 0}, /* 2.816 MHz, smp freq = 11Khz */
+ {.xscale = 1, .yscale = 6, .eq = 0}, /* 4.096 MHz, smp freq = 16Khz */
+ {.xscale = 11, .yscale = 48, .eq = 0}, /* 5.632 MHz, smp freq = 22Khz */
+
+ /*
+ * with parent clk = 49.152, freq gen is 8.192 MHz, smp freq = 32Khz
+ * with parent clk = 12.288, freq gen is 2.048 MHz, smp freq = 8Khz
+ */
+ {.xscale = 1, .yscale = 3, .eq = 0},
+
+ /* For parent clk = 49.152 MHz */
+ {.xscale = 17, .yscale = 37, .eq = 0}, /* 11.289 MHz, smp freq = 44Khz*/
+
{.xscale = 1, .yscale = 2, .eq = 0}, /* 12.288 MHz */
};
@@ -374,9 +388,6 @@ void __init spear1310_clk_init(void)
{
struct clk *clk, *clk1;
- clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
- clk_register_clkdev(clk, "apb_pclk", NULL);
-
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -401,7 +412,7 @@ void __init spear1310_clk_init(void)
clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_RTC_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "fc900000.rtc");
+ clk_register_clkdev(clk, NULL, "e0580000.rtc");
/* clock derived from 24 or 25 MHz osc clk */
/* vco-pll */
@@ -483,13 +494,18 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "ddr_clk", NULL);
/* clock derived from pll1 clk */
- clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 2);
+ clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+ CLK_SET_RATE_PARENT, 1, 2);
clk_register_clkdev(clk, "cpu_clk", NULL);
clk = clk_register_fixed_factor(NULL, "wdt_clk", "cpu_clk", 0, 1,
2);
clk_register_clkdev(clk, NULL, "ec800620.wdt");
+ clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+ 2);
+ clk_register_clkdev(clk, NULL, "smp_twd");
+
clk = clk_register_fixed_factor(NULL, "ahb_clk", "pll1_clk", 0, 1,
6);
clk_register_clkdev(clk, "ahb_clk", NULL);
@@ -547,14 +563,14 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
- ARRAY_SIZE(uart0_parents), 0, SPEAR1310_PERIP_CLK_CFG,
- SPEAR1310_UART_CLK_SHIFT, SPEAR1310_UART_CLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+ SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT,
+ SPEAR1310_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
- clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
- SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UART_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+ CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+ SPEAR1310_UART_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "e0000000.serial");
clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
@@ -563,9 +579,9 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
- SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SDHCI_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+ SPEAR1310_SDHCI_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "b3000000.sdhci");
clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -574,9 +590,9 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
- SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CFXD_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+ SPEAR1310_CFXD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "b2800000.cf");
clk_register_clkdev(clk, NULL, "arasan_xd");
@@ -587,9 +603,9 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
- ARRAY_SIZE(c3_parents), 0, SPEAR1310_PERIP_CLK_CFG,
- SPEAR1310_C3_CLK_SHIFT, SPEAR1310_C3_CLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+ SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT,
+ SPEAR1310_C3_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "c3_mclk", NULL);
clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
@@ -615,7 +631,7 @@ void __init spear1310_clk_init(void)
ARRAY_SIZE(gmac_phy_parents), 0,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, NULL, "stmmacphy.0");
+ clk_register_clkdev(clk, "stmmacphy.0", NULL);
/* clcd */
clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -630,22 +646,22 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "clcd_syn_clk", NULL);
clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
- ARRAY_SIZE(clcd_pixel_parents), 0,
+ ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+ clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CLCD_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "clcd_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e1000000.clcd");
/* i2s */
clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG,
SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK,
0, &_lock);
- clk_register_clkdev(clk, "i2s_src_clk", NULL);
+ clk_register_clkdev(clk, "i2s_src_mclk", NULL);
clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
SPEAR1310_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
@@ -653,10 +669,10 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
- ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1310_I2S_CLK_CFG,
- SPEAR1310_I2S_REF_SHIFT, SPEAR1310_I2S_REF_SEL_MASK, 0,
- &_lock);
- clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+ ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+ SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT,
+ SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock);
+ clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_I2S_REF_PAD_CLK_ENB,
@@ -664,7 +680,7 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk",
- "i2s_ref_pad_clk", 0, SPEAR1310_I2S_CLK_CFG,
+ "i2s_ref_mclk", 0, SPEAR1310_I2S_CLK_CFG,
&i2s_sclk_masks, i2s_sclk_rtbl,
ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
@@ -705,35 +721,37 @@ void __init spear1310_clk_init(void)
clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC0_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "usbh.0_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e4000000.ohci");
+ clk_register_clkdev(clk, NULL, "e4800000.ehci");
clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC1_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "usbh.1_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e5000000.ohci");
+ clk_register_clkdev(clk, NULL, "e5800000.ehci");
clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UOC_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "uoc");
+ clk_register_clkdev(clk, NULL, "e3800000.otg");
clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
0, &_lock);
clk_register_clkdev(clk, NULL, "dw_pcie.0");
- clk_register_clkdev(clk, NULL, "ahci.0");
+ clk_register_clkdev(clk, NULL, "b1000000.ahci");
clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
0, &_lock);
clk_register_clkdev(clk, NULL, "dw_pcie.1");
- clk_register_clkdev(clk, NULL, "ahci.1");
+ clk_register_clkdev(clk, NULL, "b1800000.ahci");
clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
0, &_lock);
clk_register_clkdev(clk, NULL, "dw_pcie.2");
- clk_register_clkdev(clk, NULL, "ahci.2");
+ clk_register_clkdev(clk, NULL, "b4000000.ahci");
clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SYSRAM0_CLK_ENB, 0,
@@ -751,10 +769,10 @@ void __init spear1310_clk_init(void)
clk_register_clkdev(clk, "adc_syn_clk", NULL);
clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
- SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_ADC_CLK_ENB, 0,
- &_lock);
- clk_register_clkdev(clk, NULL, "adc_clk");
+ clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+ SPEAR1310_ADC_CLK_ENB, 0, &_lock);
+ clk_register_clkdev(clk, NULL, "e0080000.adc");
/* clock derived from apb clk */
clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0,
@@ -916,15 +934,15 @@ void __init spear1310_clk_init(void)
SPEAR1310_RAS_CTRL_REG1,
SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT,
SPEAR1310_PHY_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, NULL, "stmmacphy.1");
- clk_register_clkdev(clk, NULL, "stmmacphy.2");
- clk_register_clkdev(clk, NULL, "stmmacphy.4");
+ clk_register_clkdev(clk, "stmmacphy.1", NULL);
+ clk_register_clkdev(clk, "stmmacphy.2", NULL);
+ clk_register_clkdev(clk, "stmmacphy.4", NULL);
clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
ARRAY_SIZE(rmii_phy_parents), 0,
SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
SPEAR1310_PHY_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, NULL, "stmmacphy.3");
+ clk_register_clkdev(clk, "stmmacphy.3", NULL);
clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index 2352cee7f645..82abea366b78 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -190,6 +190,7 @@ static struct pll_rate_tbl pll4_rtbl[] = {
* different values of vco1div2
*/
static struct frac_rate_tbl amba_synth_rtbl[] = {
+ {.div = 0x073A8}, /* for vco1div2 = 600 MHz */
{.div = 0x06062}, /* for vco1div2 = 500 MHz */
{.div = 0x04D1B}, /* for vco1div2 = 400 MHz */
{.div = 0x04000}, /* for vco1div2 = 332 MHz */
@@ -220,6 +221,12 @@ static struct frac_rate_tbl amba_synth_rtbl[] = {
* 500 400 200 0x02800
* 500 500 250 0x02000
* --------------------------------------------------------------------
+ * 600 200 100 0x06000
+ * 600 250 125 0x04CCE
+ * 600 332 166 0x039D5
+ * 600 400 200 0x03000
+ * 600 500 250 0x02666
+ * --------------------------------------------------------------------
* 664 200 100 0x06a38
* 664 250 125 0x054FD
* 664 332 166 0x04000
@@ -238,28 +245,50 @@ static struct frac_rate_tbl sys_synth_rtbl[] = {
{.div = 0x08000},
{.div = 0x06a38},
{.div = 0x06666},
+ {.div = 0x06000},
{.div = 0x054FD},
{.div = 0x05000},
{.div = 0x04D18},
+ {.div = 0x04CCE},
{.div = 0x04000},
+ {.div = 0x039D5},
{.div = 0x0351E},
{.div = 0x03333},
{.div = 0x03031},
+ {.div = 0x03000},
{.div = 0x02A7E},
{.div = 0x02800},
{.div = 0x0268D},
+ {.div = 0x02666},
{.div = 0x02000},
};
/* aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl aux_rtbl[] = {
- /* For VCO1div2 = 500 MHz */
- {.xscale = 10, .yscale = 204, .eq = 0}, /* 12.29 MHz */
- {.xscale = 4, .yscale = 21, .eq = 0}, /* 48 MHz */
- {.xscale = 2, .yscale = 6, .eq = 0}, /* 83 MHz */
- {.xscale = 2, .yscale = 4, .eq = 0}, /* 125 MHz */
- {.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
- {.xscale = 1, .yscale = 2, .eq = 1}, /* 250 MHz */
+ /* 12.29MHz for vic1div2=600MHz and 10.24MHz for VCO1div2=500MHz */
+ {.xscale = 5, .yscale = 122, .eq = 0},
+ /* 14.70MHz for vic1div2=600MHz and 12.29MHz for VCO1div2=500MHz */
+ {.xscale = 10, .yscale = 204, .eq = 0},
+ /* 48MHz for vic1div2=600MHz and 40 MHz for VCO1div2=500MHz */
+ {.xscale = 4, .yscale = 25, .eq = 0},
+ /* 57.14MHz for vic1div2=600MHz and 48 MHz for VCO1div2=500MHz */
+ {.xscale = 4, .yscale = 21, .eq = 0},
+ /* 83.33MHz for vic1div2=600MHz and 69.44MHz for VCO1div2=500MHz */
+ {.xscale = 5, .yscale = 18, .eq = 0},
+ /* 100MHz for vic1div2=600MHz and 83.33 MHz for VCO1div2=500MHz */
+ {.xscale = 2, .yscale = 6, .eq = 0},
+ /* 125MHz for vic1div2=600MHz and 104.1MHz for VCO1div2=500MHz */
+ {.xscale = 5, .yscale = 12, .eq = 0},
+ /* 150MHz for vic1div2=600MHz and 125MHz for VCO1div2=500MHz */
+ {.xscale = 2, .yscale = 4, .eq = 0},
+ /* 166MHz for vic1div2=600MHz and 138.88MHz for VCO1div2=500MHz */
+ {.xscale = 5, .yscale = 18, .eq = 1},
+ /* 200MHz for vic1div2=600MHz and 166MHz for VCO1div2=500MHz */
+ {.xscale = 1, .yscale = 3, .eq = 1},
+ /* 250MHz for vic1div2=600MHz and 208.33MHz for VCO1div2=500MHz */
+ {.xscale = 5, .yscale = 12, .eq = 1},
+ /* 300MHz for vic1div2=600MHz and 250MHz for VCO1div2=500MHz */
+ {.xscale = 1, .yscale = 2, .eq = 1},
};
/* gmac rate configuration table, in ascending order of rates */
@@ -273,16 +302,23 @@ static struct aux_rate_tbl gmac_rtbl[] = {
/* clcd rate configuration table, in ascending order of rates */
static struct frac_rate_tbl clcd_rtbl[] = {
+ {.div = 0x18000}, /* 25 Mhz , for vc01div4 = 300 MHz*/
+ {.div = 0x1638E}, /* 27 Mhz , for vc01div4 = 300 MHz*/
{.div = 0x14000}, /* 25 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x1284B}, /* 27 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x0D8D3}, /* 58 Mhz , for vco1div4 = 393 MHz */
{.div = 0x0B72C}, /* 58 Mhz , for vco1div4 = 332 MHz */
+ {.div = 0x0A584}, /* 58 Mhz , for vco1div4 = 300 MHz */
+ {.div = 0x093B1}, /* 65 Mhz , for vc01div4 = 300 MHz*/
{.div = 0x089EE}, /* 58 Mhz , for vc01div4 = 250 MHz*/
+ {.div = 0x081BA}, /* 74 Mhz , for vc01div4 = 300 MHz*/
{.div = 0x07BA0}, /* 65 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x06f1C}, /* 72 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x06E58}, /* 58 Mhz , for vco1div4 = 200 MHz */
{.div = 0x06c1B}, /* 74 Mhz , for vc01div4 = 250 MHz*/
+ {.div = 0x058E3}, /* 108 Mhz , for vc01div4 = 300 MHz*/
{.div = 0x04A12}, /* 108 Mhz , for vc01div4 = 250 MHz*/
+ {.div = 0x040A5}, /* 148.5 Mhz , for vc01div4 = 300 MHz*/
{.div = 0x0378E}, /* 144 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x0360D}, /* 148 Mhz , for vc01div4 = 250 MHz*/
{.div = 0x035E0}, /* 148.5 MHz, for vc01div4 = 250 MHz*/
@@ -351,26 +387,37 @@ static struct aux_rate_tbl adc_rtbl[] = {
/* General synth rate configuration table, in ascending order of rates */
static struct frac_rate_tbl gen_rtbl[] = {
- /* For vco1div4 = 250 MHz */
- {.div = 0x1624E}, /* 22.5792 MHz */
- {.div = 0x14585}, /* 24.576 MHz */
- {.div = 0x14000}, /* 25 MHz */
- {.div = 0x0B127}, /* 45.1584 MHz */
- {.div = 0x0A000}, /* 50 MHz */
- {.div = 0x061A8}, /* 81.92 MHz */
- {.div = 0x05000}, /* 100 MHz */
- {.div = 0x02800}, /* 200 MHz */
- {.div = 0x02620}, /* 210 MHz */
- {.div = 0x02460}, /* 220 MHz */
- {.div = 0x022C0}, /* 230 MHz */
- {.div = 0x02160}, /* 240 MHz */
- {.div = 0x02000}, /* 250 MHz */
+ {.div = 0x1A92B}, /* 22.5792 MHz for vco1div4=300 MHz*/
+ {.div = 0x186A0}, /* 24.576 MHz for vco1div4=300 MHz*/
+ {.div = 0x18000}, /* 25 MHz for vco1div4=300 MHz*/
+ {.div = 0x1624E}, /* 22.5792 MHz for vco1div4=250 MHz*/
+ {.div = 0x14585}, /* 24.576 MHz for vco1div4=250 MHz*/
+ {.div = 0x14000}, /* 25 MHz for vco1div4=250 MHz*/
+ {.div = 0x0D495}, /* 45.1584 MHz for vco1div4=300 MHz*/
+ {.div = 0x0C000}, /* 50 MHz for vco1div4=300 MHz*/
+ {.div = 0x0B127}, /* 45.1584 MHz for vco1div4=250 MHz*/
+ {.div = 0x0A000}, /* 50 MHz for vco1div4=250 MHz*/
+ {.div = 0x07530}, /* 81.92 MHz for vco1div4=300 MHz*/
+ {.div = 0x061A8}, /* 81.92 MHz for vco1div4=250 MHz*/
+ {.div = 0x06000}, /* 100 MHz for vco1div4=300 MHz*/
+ {.div = 0x05000}, /* 100 MHz for vco1div4=250 MHz*/
+ {.div = 0x03000}, /* 200 MHz for vco1div4=300 MHz*/
+ {.div = 0x02DB6}, /* 210 MHz for vco1div4=300 MHz*/
+ {.div = 0x02BA2}, /* 220 MHz for vco1div4=300 MHz*/
+ {.div = 0x029BD}, /* 230 MHz for vco1div4=300 MHz*/
+ {.div = 0x02800}, /* 200 MHz for vco1div4=250 MHz*/
+ {.div = 0x02666}, /* 250 MHz for vco1div4=300 MHz*/
+ {.div = 0x02620}, /* 210 MHz for vco1div4=250 MHz*/
+ {.div = 0x02460}, /* 220 MHz for vco1div4=250 MHz*/
+ {.div = 0x022C0}, /* 230 MHz for vco1div4=250 MHz*/
+ {.div = 0x02160}, /* 240 MHz for vco1div4=250 MHz*/
+ {.div = 0x02000}, /* 250 MHz for vco1div4=250 MHz*/
};
/* clock parents */
static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
static const char *sys_parents[] = { "pll1_clk", "pll1_clk", "pll1_clk",
- "pll1_clk", "sys_synth_clk", "sys_synth_clk", "pll2_clk", "pll3_clk", };
+ "pll1_clk", "sys_syn_clk", "sys_syn_clk", "pll2_clk", "pll3_clk", };
static const char *ahb_parents[] = { "cpu_div3_clk", "amba_syn_clk", };
static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
static const char *uart0_parents[] = { "pll5_clk", "osc_24m_clk",
@@ -391,16 +438,13 @@ static const char *spdif_in_parents[] = { "pll2_clk", "gen_syn3_clk", };
static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
"pll3_clk", };
-static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco3div2_clk",
+static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco2div2_clk",
"pll2_clk", };
void __init spear1340_clk_init(void)
{
struct clk *clk, *clk1;
- clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
- clk_register_clkdev(clk, "apb_pclk", NULL);
-
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -425,7 +469,7 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_RTC_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "fc900000.rtc");
+ clk_register_clkdev(clk, NULL, "e0580000.rtc");
/* clock derived from 24 or 25 MHz osc clk */
/* vco-pll */
@@ -499,7 +543,7 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_THSENS_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "spear_thermal");
+ clk_register_clkdev(clk, NULL, "e07008c4.thermal");
/* clock derived from pll4 clk */
clk = clk_register_fixed_factor(NULL, "ddr_clk", "pll4_clk", 0, 1,
@@ -521,7 +565,7 @@ void __init spear1340_clk_init(void)
ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL,
SPEAR1340_SCLK_SRC_SEL_SHIFT,
SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
- clk_register_clkdev(clk, "sys_clk", NULL);
+ clk_register_clkdev(clk, "sys_mclk", NULL);
clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mclk", 0, 1,
2);
@@ -535,6 +579,10 @@ void __init spear1340_clk_init(void)
2);
clk_register_clkdev(clk, NULL, "ec800620.wdt");
+ clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+ 2);
+ clk_register_clkdev(clk, NULL, "smp_twd");
+
clk = clk_register_mux(NULL, "ahb_clk", ahb_parents,
ARRAY_SIZE(ahb_parents), 0, SPEAR1340_SYS_CLK_CTRL,
SPEAR1340_HCLK_SRC_SEL_SHIFT,
@@ -594,14 +642,14 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
- ARRAY_SIZE(uart0_parents), 0, SPEAR1340_PERIP_CLK_CFG,
- SPEAR1340_UART0_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+ SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT,
+ SPEAR1340_UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
- clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
- SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UART0_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+ SPEAR1340_UART0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "e0000000.serial");
clk = clk_register_aux("uart1_syn_clk", "uart1_syn_gclk",
@@ -627,9 +675,9 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
- SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SDHCI_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+ SPEAR1340_SDHCI_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "b3000000.sdhci");
clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -638,9 +686,9 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
- SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CFXD_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+ SPEAR1340_CFXD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "b2800000.cf");
clk_register_clkdev(clk, NULL, "arasan_xd");
@@ -651,15 +699,15 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
- ARRAY_SIZE(c3_parents), 0, SPEAR1340_PERIP_CLK_CFG,
- SPEAR1340_C3_CLK_SHIFT, SPEAR1340_C3_CLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+ SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT,
+ SPEAR1340_C3_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "c3_mclk", NULL);
- clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
+ clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", CLK_SET_RATE_PARENT,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_C3_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "c3");
+ clk_register_clkdev(clk, NULL, "e1800000.c3");
/* gmac */
clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
@@ -679,7 +727,7 @@ void __init spear1340_clk_init(void)
ARRAY_SIZE(gmac_phy_parents), 0,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, NULL, "stmmacphy.0");
+ clk_register_clkdev(clk, "stmmacphy.0", NULL);
/* clcd */
clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -694,33 +742,34 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk, "clcd_syn_clk", NULL);
clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
- ARRAY_SIZE(clcd_pixel_parents), 0,
+ ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+ clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CLCD_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "clcd_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e1000000.clcd");
/* i2s */
clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG,
SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK,
0, &_lock);
- clk_register_clkdev(clk, "i2s_src_clk", NULL);
+ clk_register_clkdev(clk, "i2s_src_mclk", NULL);
- clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
- SPEAR1340_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
+ clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_I2S_CLK_CFG,
+ &i2s_prs1_masks, i2s_prs1_rtbl,
ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
- ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1340_I2S_CLK_CFG,
- SPEAR1340_I2S_REF_SHIFT, SPEAR1340_I2S_REF_SEL_MASK, 0,
- &_lock);
- clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+ ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+ SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT,
+ SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock);
+ clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_I2S_REF_PAD_CLK_ENB,
@@ -769,23 +818,25 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC0_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "usbh.0_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e4000000.ohci");
+ clk_register_clkdev(clk, NULL, "e4800000.ehci");
clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC1_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, "usbh.1_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e5000000.ohci");
+ clk_register_clkdev(clk, NULL, "e5800000.ehci");
clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UOC_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "uoc");
+ clk_register_clkdev(clk, NULL, "e3800000.otg");
clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
0, &_lock);
clk_register_clkdev(clk, NULL, "dw_pcie");
- clk_register_clkdev(clk, NULL, "ahci");
+ clk_register_clkdev(clk, NULL, "b1000000.ahci");
clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SYSRAM0_CLK_ENB, 0,
@@ -803,10 +854,10 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk, "adc_syn_clk", NULL);
clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
- clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
- SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_ADC_CLK_ENB, 0,
- &_lock);
- clk_register_clkdev(clk, NULL, "adc_clk");
+ clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+ SPEAR1340_ADC_CLK_ENB, 0, &_lock);
+ clk_register_clkdev(clk, NULL, "e0080000.adc");
/* clock derived from apb clk */
clk = clk_register_gate(NULL, "ssp_clk", "apb_clk", 0,
@@ -827,12 +878,12 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "i2s_play_clk", "apb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_PLAY_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "b2400000.i2s");
+ clk_register_clkdev(clk, NULL, "b2400000.i2s-play");
clk = clk_register_gate(NULL, "i2s_rec_clk", "apb_clk", 0,
SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_REC_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "b2000000.i2s");
+ clk_register_clkdev(clk, NULL, "b2000000.i2s-rec");
clk = clk_register_gate(NULL, "kbd_clk", "apb_clk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_KBD_CLK_ENB, 0,
@@ -844,37 +895,37 @@ void __init spear1340_clk_init(void)
ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG,
SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
+ clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL);
clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG,
SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
- clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
+ clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL);
- clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
+ clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_mclk", 0,
SPEAR1340_GEN_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
&_lock);
clk_register_clkdev(clk, "gen_syn0_clk", NULL);
- clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
+ clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_mclk", 0,
SPEAR1340_GEN_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
&_lock);
clk_register_clkdev(clk, "gen_syn1_clk", NULL);
- clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
+ clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_mclk", 0,
SPEAR1340_GEN_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
&_lock);
clk_register_clkdev(clk, "gen_syn2_clk", NULL);
- clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
+ clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_mclk", 0,
SPEAR1340_GEN_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
&_lock);
clk_register_clkdev(clk, "gen_syn3_clk", NULL);
- clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk", 0,
- SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_MALI_CLK_ENB, 0,
- &_lock);
+ clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+ SPEAR1340_MALI_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "mali");
clk = clk_register_gate(NULL, "cec0_clk", "ahb_clk", 0,
@@ -888,26 +939,26 @@ void __init spear1340_clk_init(void)
clk_register_clkdev(clk, NULL, "spear_cec.1");
clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
- ARRAY_SIZE(spdif_out_parents), 0,
+ ARRAY_SIZE(spdif_out_parents), CLK_SET_RATE_PARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "spdif_out_mclk", NULL);
- clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk", 0,
- SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_OUT_CLK_ENB,
- 0, &_lock);
- clk_register_clkdev(clk, NULL, "spdif-out");
+ clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+ SPEAR1340_SPDIF_OUT_CLK_ENB, 0, &_lock);
+ clk_register_clkdev(clk, NULL, "d0000000.spdif-out");
clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
- ARRAY_SIZE(spdif_in_parents), 0,
+ ARRAY_SIZE(spdif_in_parents), CLK_SET_RATE_PARENT,
SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "spdif_in_mclk", NULL);
- clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk", 0,
- SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_IN_CLK_ENB, 0,
- &_lock);
- clk_register_clkdev(clk, NULL, "spdif-in");
+ clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk",
+ CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+ SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
+ clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
@@ -917,7 +968,7 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "plgpio");
+ clk_register_clkdev(clk, NULL, "e2800000.gpio");
clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
@@ -937,25 +988,25 @@ void __init spear1340_clk_init(void)
clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "spear_camif.0");
+ clk_register_clkdev(clk, NULL, "d0200000.cam0");
clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "spear_camif.1");
+ clk_register_clkdev(clk, NULL, "d0300000.cam1");
clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "spear_camif.2");
+ clk_register_clkdev(clk, NULL, "d0400000.cam2");
clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "spear_camif.3");
+ clk_register_clkdev(clk, NULL, "d0500000.cam3");
- clk = clk_register_gate(NULL, "pwm_clk", "pwm_mclk", 0,
+ clk = clk_register_gate(NULL, "pwm_clk", "ahb_clk", 0,
SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PWM_CLK_ENB, 0,
&_lock);
- clk_register_clkdev(clk, NULL, "pwm");
+ clk_register_clkdev(clk, NULL, "e0180000.pwm");
}
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c
index c3157454bb3f..33d3ac588da7 100644
--- a/drivers/clk/spear/spear3xx_clock.c
+++ b/drivers/clk/spear/spear3xx_clock.c
@@ -107,6 +107,12 @@ static struct pll_rate_tbl pll_rtbl[] = {
/* aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
+ {.xscale = 1, .yscale = 81, .eq = 0}, /* 2.049 MHz */
+ {.xscale = 1, .yscale = 59, .eq = 0}, /* 2.822 MHz */
+ {.xscale = 2, .yscale = 81, .eq = 0}, /* 4.098 MHz */
+ {.xscale = 3, .yscale = 89, .eq = 0}, /* 5.644 MHz */
+ {.xscale = 4, .yscale = 81, .eq = 0}, /* 8.197 MHz */
+ {.xscale = 4, .yscale = 59, .eq = 0}, /* 11.254 MHz */
{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
@@ -157,6 +163,8 @@ static void __init spear300_clk_init(void)
1);
clk_register_clkdev(clk, NULL, "a0000000.kbd");
}
+#else
+static inline void spear300_clk_init(void) { }
#endif
/* array of all spear 310 clock lookups */
@@ -197,6 +205,8 @@ static void __init spear310_clk_init(void)
1);
clk_register_clkdev(clk, NULL, "b2200000.serial");
}
+#else
+static inline void spear310_clk_init(void) { }
#endif
/* array of all spear 320 clock lookups */
@@ -251,7 +261,7 @@ static void __init spear320_clk_init(void)
clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1,
1);
- clk_register_clkdev(clk, "pwm", NULL);
+ clk_register_clkdev(clk, NULL, "a8000000.pwm");
clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1,
1);
@@ -271,26 +281,37 @@ static void __init spear320_clk_init(void)
clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1,
1);
- clk_register_clkdev(clk, NULL, "i2s");
+ clk_register_clkdev(clk, NULL, "a9400000.i2s");
clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
- ARRAY_SIZE(i2s_ref_parents), 0, SPEAR320_CONTROL_REG,
- I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock);
+ ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT,
+ I2S_REF_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_ref_clk", NULL);
- clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk", 0, 1,
+ clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk",
+ CLK_SET_RATE_PARENT, 1,
4);
clk_register_clkdev(clk, "i2s_sclk", NULL);
+ clk = clk_register_fixed_factor(NULL, "macb1_clk", "ras_apb_clk", 0, 1,
+ 1);
+ clk_register_clkdev(clk, "hclk", "aa000000.eth");
+
+ clk = clk_register_fixed_factor(NULL, "macb2_clk", "ras_apb_clk", 0, 1,
+ 1);
+ clk_register_clkdev(clk, "hclk", "ab000000.eth");
+
clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9300000.serial");
clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
- ARRAY_SIZE(sdhci_parents), 0, SPEAR320_CONTROL_REG,
- SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock);
+ ARRAY_SIZE(sdhci_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK,
+ 0, &_lock);
clk_register_clkdev(clk, NULL, "70000000.sdhci");
clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
@@ -302,49 +323,49 @@ static void __init spear320_clk_init(void)
clk_register_clkdev(clk, NULL, "smii");
clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_CONTROL_REG,
- UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK,
+ 0, &_lock);
clk_register_clkdev(clk, NULL, "a3000000.serial");
clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a4000000.serial");
clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9100000.serial");
clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a9200000.serial");
clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "60000000.serial");
clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
- ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
- SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
- &_lock);
+ ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+ SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT,
+ SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "60100000.serial");
}
+#else
+static inline void spear320_clk_init(void) { }
#endif
void __init spear3xx_clk_init(void)
{
struct clk *clk, *clk1;
- clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
- clk_register_clkdev(clk, "apb_pclk", NULL);
-
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -380,7 +401,8 @@ void __init spear3xx_clk_init(void)
clk_register_clkdev(clk1, "pll2_clk", NULL);
/* clock derived from pll1 clk */
- clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+ clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+ CLK_SET_RATE_PARENT, 1, 1);
clk_register_clkdev(clk, "cpu_clk", NULL);
clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -395,12 +417,14 @@ void __init spear3xx_clk_init(void)
clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
- ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG,
- UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
+ ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+ PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
+ &_lock);
clk_register_clkdev(clk, "uart0_mclk", NULL);
- clk = clk_register_gate(NULL, "uart0", "uart0_mclk", 0, PERIP1_CLK_ENB,
- UART_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "uart0", "uart0_mclk",
+ CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, UART_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, NULL, "d0000000.serial");
clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk", 0,
@@ -410,40 +434,44 @@ void __init spear3xx_clk_init(void)
clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
- ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
- FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
+ ARRAY_SIZE(firda_parents), CLK_SET_RATE_PARENT,
+ PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
+ &_lock);
clk_register_clkdev(clk, "firda_mclk", NULL);
- clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
- PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "firda_clk", "firda_mclk",
+ CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, NULL, "firda");
/* gpt clocks */
clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
- ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG,
- GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+ ARRAY_SIZE(gpt0_parents), CLK_SET_RATE_PARENT,
+ PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt0");
clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
- ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG,
- GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+ ARRAY_SIZE(gpt1_parents), CLK_SET_RATE_PARENT,
+ PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mclk", NULL);
- clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
- PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk",
+ CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT1_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, NULL, "gpt1");
clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
- ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
- GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+ ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_PARENT,
+ PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mclk", NULL);
- clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
- PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk",
+ CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT2_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, NULL, "gpt2");
/* general synths clocks */
@@ -480,7 +508,9 @@ void __init spear3xx_clk_init(void)
/* clock derived from pll3 clk */
clk = clk_register_gate(NULL, "usbh_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
USBH_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, "usbh_clk", NULL);
+ clk_register_clkdev(clk, NULL, "e1800000.ehci");
+ clk_register_clkdev(clk, NULL, "e1900000.ohci");
+ clk_register_clkdev(clk, NULL, "e2100000.ohci");
clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
1);
@@ -492,7 +522,7 @@ void __init spear3xx_clk_init(void)
clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
USBD_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "designware_udc");
+ clk_register_clkdev(clk, NULL, "e1100000.usbd");
/* clock derived from ahb clk */
clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
@@ -540,7 +570,7 @@ void __init spear3xx_clk_init(void)
/* clock derived from apb clk */
clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
ADC_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "adc");
+ clk_register_clkdev(clk, NULL, "d0080000.adc");
clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
GPIO_CLK_ENB, 0, &_lock);
@@ -579,20 +609,24 @@ void __init spear3xx_clk_init(void)
RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_pll3_clk", NULL);
- clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk", 0,
- RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk",
+ CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, "ras_syn0_gclk", NULL);
- clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk", 0,
- RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk",
+ CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, "ras_syn1_gclk", NULL);
- clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk", 0,
- RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk",
+ CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, "ras_syn2_gclk", NULL);
- clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk", 0,
- RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0, &_lock);
+ clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk",
+ CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0,
+ &_lock);
clk_register_clkdev(clk, "ras_syn3_gclk", NULL);
if (of_machine_is_compatible("st,spear300"))
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
index a98d0866f541..e862a333ad30 100644
--- a/drivers/clk/spear/spear6xx_clock.c
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -92,6 +92,7 @@ static struct pll_rate_tbl pll_rtbl[] = {
/* aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
+ {.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
@@ -118,9 +119,6 @@ void __init spear6xx_clk_init(void)
{
struct clk *clk, *clk1;
- clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
- clk_register_clkdev(clk, "apb_pclk", NULL);
-
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -156,7 +154,8 @@ void __init spear6xx_clk_init(void)
clk_register_clkdev(clk, NULL, "wdt");
/* clock derived from pll1 clk */
- clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+ clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+ CLK_SET_RATE_PARENT, 1, 1);
clk_register_clkdev(clk, "cpu_clk", NULL);
clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -261,11 +260,13 @@ void __init spear6xx_clk_init(void)
/* clock derived from pll3 clk */
clk = clk_register_gate(NULL, "usbh0_clk", "pll3_clk", 0,
PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "usbh.0_clk");
+ clk_register_clkdev(clk, NULL, "e1800000.ehci");
+ clk_register_clkdev(clk, NULL, "e1900000.ohci");
clk = clk_register_gate(NULL, "usbh1_clk", "pll3_clk", 0,
PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "usbh.1_clk");
+ clk_register_clkdev(clk, NULL, "e2000000.ehci");
+ clk_register_clkdev(clk, NULL, "e2100000.ohci");
clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
USBD_CLK_ENB, 0, &_lock);
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile
index 858fbfe66281..bcc0c11a507c 100644
--- a/drivers/clk/ux500/Makefile
+++ b/drivers/clk/ux500/Makefile
@@ -10,3 +10,6 @@ obj-y += clk-prcmu.o
obj-y += u8500_clk.o
obj-y += u9540_clk.o
obj-y += u8540_clk.o
+
+# ABX500 clock driver
+obj-y += abx500-clk.o
diff --git a/drivers/clk/ux500/abx500-clk.c b/drivers/clk/ux500/abx500-clk.c
new file mode 100644
index 000000000000..e27c52317ffe
--- /dev/null
+++ b/drivers/clk/ux500/abx500-clk.c
@@ -0,0 +1,73 @@
+/*
+ * abx500 clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/abx500/ab8500.h>
+
+/* TODO: Add clock implementations here */
+
+
+/* Clock definitions for ab8500 */
+static int ab8500_reg_clks(struct device *dev)
+{
+ return 0;
+}
+
+/* Clock definitions for ab8540 */
+static int ab8540_reg_clks(struct device *dev)
+{
+ return 0;
+}
+
+/* Clock definitions for ab9540 */
+static int ab9540_reg_clks(struct device *dev)
+{
+ return 0;
+}
+
+static int __devinit abx500_clk_probe(struct platform_device *pdev)
+{
+ struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent);
+ int ret;
+
+ if (is_ab8500(parent) || is_ab8505(parent)) {
+ ret = ab8500_reg_clks(&pdev->dev);
+ } else if (is_ab8540(parent)) {
+ ret = ab8540_reg_clks(&pdev->dev);
+ } else if (is_ab9540(parent)) {
+ ret = ab9540_reg_clks(&pdev->dev);
+ } else {
+ dev_err(&pdev->dev, "non supported plf id\n");
+ return -ENODEV;
+ }
+
+ return ret;
+}
+
+static struct platform_driver abx500_clk_driver = {
+ .driver = {
+ .name = "abx500-clk",
+ .owner = THIS_MODULE,
+ },
+ .probe = abx500_clk_probe,
+};
+
+static int __init abx500_clk_init(void)
+{
+ return platform_driver_register(&abx500_clk_driver);
+}
+
+arch_initcall(abx500_clk_init);
+
+MODULE_AUTHOR("Ulf Hansson <ulf.hansson@linaro.org");
+MODULE_DESCRIPTION("ABX500 clk driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 930cdfeb47ab..74faa7e3cf59 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -133,6 +133,40 @@ out_error:
hw->init->name);
}
+static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
+{
+ int err;
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+ err = prcmu_request_ape_opp_100_voltage(true);
+ if (err) {
+ pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
+ __func__, hw->init->name);
+ return err;
+ }
+
+ err = prcmu_request_clock(clk->cg_sel, true);
+ if (err)
+ prcmu_request_ape_opp_100_voltage(false);
+
+ return err;
+}
+
+static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
+{
+ struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+ if (prcmu_request_clock(clk->cg_sel, false))
+ goto out_error;
+ if (prcmu_request_ape_opp_100_voltage(false))
+ goto out_error;
+ return;
+
+out_error:
+ pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+ hw->init->name);
+}
+
static struct clk_ops clk_prcmu_scalable_ops = {
.prepare = clk_prcmu_prepare,
.unprepare = clk_prcmu_unprepare,
@@ -153,6 +187,13 @@ static struct clk_ops clk_prcmu_gate_ops = {
.recalc_rate = clk_prcmu_recalc_rate,
};
+static struct clk_ops clk_prcmu_scalable_rate_ops = {
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+ .round_rate = clk_prcmu_round_rate,
+ .set_rate = clk_prcmu_set_rate,
+};
+
static struct clk_ops clk_prcmu_rate_ops = {
.is_enabled = clk_prcmu_is_enabled,
.recalc_rate = clk_prcmu_recalc_rate,
@@ -167,6 +208,17 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
.recalc_rate = clk_prcmu_recalc_rate,
};
+static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
+ .prepare = clk_prcmu_opp_volt_prepare,
+ .unprepare = clk_prcmu_opp_volt_unprepare,
+ .enable = clk_prcmu_enable,
+ .disable = clk_prcmu_disable,
+ .is_enabled = clk_prcmu_is_enabled,
+ .recalc_rate = clk_prcmu_recalc_rate,
+ .round_rate = clk_prcmu_round_rate,
+ .set_rate = clk_prcmu_set_rate,
+};
+
static struct clk *clk_reg_prcmu(const char *name,
const char *parent_name,
u8 cg_sel,
@@ -233,6 +285,16 @@ struct clk *clk_reg_prcmu_gate(const char *name,
&clk_prcmu_gate_ops);
}
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+ &clk_prcmu_scalable_rate_ops);
+}
+
struct clk *clk_reg_prcmu_rate(const char *name,
const char *parent_name,
u8 cg_sel,
@@ -250,3 +312,13 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
&clk_prcmu_opp_gate_ops);
}
+
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags)
+{
+ return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+ &clk_prcmu_opp_volt_scalable_ops);
+}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
index 836d7d16751e..c3e449169a83 100644
--- a/drivers/clk/ux500/clk.h
+++ b/drivers/clk/ux500/clk.h
@@ -35,6 +35,12 @@ struct clk *clk_reg_prcmu_gate(const char *name,
u8 cg_sel,
unsigned long flags);
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags);
+
struct clk *clk_reg_prcmu_rate(const char *name,
const char *parent_name,
u8 cg_sel,
@@ -45,4 +51,10 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
u8 cg_sel,
unsigned long flags);
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+ const char *parent_name,
+ u8 cg_sel,
+ unsigned long rate,
+ unsigned long flags);
+
#endif /* __UX500_CLK_H */
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index e2c17d187d98..7d0e0258f204 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -170,10 +170,11 @@ void u8500_clk_init(void)
clk_register_clkdev(clk, NULL, "mtu0");
clk_register_clkdev(clk, NULL, "mtu1");
- clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT);
+ clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
+ 100000000,
+ CLK_IS_ROOT|CLK_SET_RATE_GATE);
clk_register_clkdev(clk, NULL, "sdmmc");
-
clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
clk_register_clkdev(clk, "dsihs2", "mcde");
@@ -205,16 +206,18 @@ void u8500_clk_init(void)
clk_register_clkdev(clk, "dsilp2", "dsilink.2");
clk_register_clkdev(clk, "dsilp2", "mcde");
- clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
- CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
- CLK_IGNORE_UNUSED);
+ clk = clk_reg_prcmu_scalable_rate("armss", NULL,
+ PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+ clk_register_clkdev(clk, "armss", NULL);
+
+ clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
+ CLK_IGNORE_UNUSED, 1, 2);
clk_register_clkdev(clk, NULL, "smp_twd");
/*
* FIXME: Add special handled PRCMU clocks here:
- * 1. clk_arm, use PRCMU_ARMCLK.
- * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
- * 3. ab9540_clkout1yuv, see clkout0yuv
+ * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+ * 2. ab9540_clkout1yuv, see clkout0yuv
*/
/* PRCC P-clocks */
@@ -323,7 +326,7 @@ void u8500_clk_init(void)
clk_register_clkdev(clk, NULL, "gpioblock1");
clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", U8500_CLKRST2_BASE,
- BIT(11), 0);
+ BIT(12), 0);
clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE,
BIT(0), 0);
@@ -347,6 +350,8 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE,
BIT(5), 0);
+ clk_register_clkdev(clk, "apb_pclk", "ske");
+ clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE,
BIT(6), 0);
@@ -375,6 +380,7 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE,
BIT(0), 0);
+ clk_register_clkdev(clk, "apb_pclk", "rng");
clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE,
BIT(1), 0);
@@ -503,6 +509,8 @@ void u8500_clk_init(void)
clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE);
+ clk_register_clkdev(clk, NULL, "ske");
+ clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE);
@@ -515,5 +523,5 @@ void u8500_clk_init(void)
/* Periph6 */
clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE);
-
+ clk_register_clkdev(clk, NULL, "rng");
}
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c0a0f6478798..ec3b88fe3e6d 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,4 +1,7 @@
# Makefile for Versatile-specific clocks
obj-$(CONFIG_ICST) += clk-icst.o
obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
+obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
+obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
+obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index f555b50a5fa5..67ccf4aa7277 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -3,6 +3,12 @@
* We wrap the custom interface from <asm/hardware/icst.h> into the generic
* clock framework.
*
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
* TODO: when all ARM reference designs are migrated to generic clocks, the
* ICST clock code from the ARM tree should probably be merged into this
* file.
@@ -11,33 +17,74 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
+#include <linux/io.h>
#include "clk-icst.h"
/**
* struct clk_icst - ICST VCO clock wrapper
* @hw: corresponding clock hardware entry
+ * @vcoreg: VCO register address
+ * @lockreg: VCO lock register address
* @params: parameters for this ICST instance
* @rate: current rate
- * @setvco: function to commit ICST settings to hardware
*/
struct clk_icst {
struct clk_hw hw;
+ void __iomem *vcoreg;
+ void __iomem *lockreg;
const struct icst_params *params;
unsigned long rate;
- struct icst_vco (*getvco)(void);
- void (*setvco)(struct icst_vco);
};
#define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
+/**
+ * vco_get() - get ICST VCO settings from a certain register
+ * @vcoreg: register containing the VCO settings
+ */
+static struct icst_vco vco_get(void __iomem *vcoreg)
+{
+ u32 val;
+ struct icst_vco vco;
+
+ val = readl(vcoreg);
+ vco.v = val & 0x1ff;
+ vco.r = (val >> 9) & 0x7f;
+ vco.s = (val >> 16) & 03;
+ return vco;
+}
+
+/**
+ * vco_set() - commit changes to an ICST VCO
+ * @locreg: register to poke to unlock the VCO for writing
+ * @vcoreg: register containing the VCO settings
+ * @vco: ICST VCO parameters to commit
+ */
+static void vco_set(void __iomem *lockreg,
+ void __iomem *vcoreg,
+ struct icst_vco vco)
+{
+ u32 val;
+
+ val = readl(vcoreg) & ~0x7ffff;
+ val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+ /* This magic unlocks the VCO so it can be controlled */
+ writel(0xa05f, lockreg);
+ writel(val, vcoreg);
+ /* This locks the VCO again */
+ writel(0, lockreg);
+}
+
+
static unsigned long icst_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_icst *icst = to_icst(hw);
struct icst_vco vco;
- vco = icst->getvco();
+ vco = vco_get(icst->vcoreg);
icst->rate = icst_hz(icst->params, vco);
return icst->rate;
}
@@ -60,7 +107,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
vco = icst_hz_to_vco(icst->params, rate);
icst->rate = icst_hz(icst->params, vco);
- icst->setvco(vco);
+ vco_set(icst->vcoreg, icst->lockreg, vco);
return 0;
}
@@ -70,8 +117,9 @@ static const struct clk_ops icst_ops = {
.set_rate = icst_set_rate,
};
-struct clk * __init icst_clk_register(struct device *dev,
- const struct clk_icst_desc *desc)
+struct clk *icst_clk_register(struct device *dev,
+ const struct clk_icst_desc *desc,
+ void __iomem *base)
{
struct clk *clk;
struct clk_icst *icst;
@@ -89,8 +137,8 @@ struct clk * __init icst_clk_register(struct device *dev,
init.num_parents = 0;
icst->hw.init = &init;
icst->params = desc->params;
- icst->getvco = desc->getvco;
- icst->setvco = desc->setvco;
+ icst->vcoreg = base + desc->vco_offset;
+ icst->lockreg = base + desc->lock_offset;
clk = clk_register(dev, &icst->hw);
if (IS_ERR(clk))
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
index 71b4c56c1410..dad51b6ffd00 100644
--- a/drivers/clk/versatile/clk-icst.h
+++ b/drivers/clk/versatile/clk-icst.h
@@ -1,10 +1,18 @@
#include <asm/hardware/icst.h>
+/**
+ * struct clk_icst_desc - descriptor for the ICST VCO
+ * @params: ICST parameters
+ * @vco_offset: offset to the ICST VCO from the provided memory base
+ * @lock_offset: offset to the ICST VCO locking register from the provided
+ * memory base
+ */
struct clk_icst_desc {
const struct icst_params *params;
- struct icst_vco (*getvco)(void);
- void (*setvco)(struct icst_vco);
+ u32 vco_offset;
+ u32 lock_offset;
};
struct clk *icst_clk_register(struct device *dev,
- const struct clk_icst_desc *desc);
+ const struct clk_icst_desc *desc,
+ void __iomem *base);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
new file mode 100644
index 000000000000..369139af2a3b
--- /dev/null
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -0,0 +1,97 @@
+/*
+ * Clock driver for the ARM Integrator/IM-PD1 board
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can 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/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
+
+#include <mach/impd1.h>
+
+#include "clk-icst.h"
+
+struct impd1_clk {
+ struct clk *vcoclk;
+ struct clk *uartclk;
+ struct clk_lookup *clks[3];
+};
+
+static struct impd1_clk impd1_clks[4];
+
+/*
+ * There are two VCO's on the IM-PD1 but only one is used by the
+ * kernel, that is why we are only implementing the control of
+ * IMPD1_OSC1 here.
+ */
+
+static const struct icst_params impd1_vco_params = {
+ .ref = 24000000, /* 24 MHz */
+ .vco_max = ICST525_VCO_MAX_3V,
+ .vco_min = ICST525_VCO_MIN,
+ .vd_min = 12,
+ .vd_max = 519,
+ .rd_min = 3,
+ .rd_max = 120,
+ .s2div = icst525_s2div,
+ .idx2s = icst525_idx2s,
+};
+
+static const struct clk_icst_desc impd1_icst1_desc = {
+ .params = &impd1_vco_params,
+ .vco_offset = IMPD1_OSC1,
+ .lock_offset = IMPD1_LOCK,
+};
+
+/**
+ * integrator_impd1_clk_init() - set up the integrator clock tree
+ * @base: base address of the logic module (LM)
+ * @id: the ID of this LM
+ */
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
+{
+ struct impd1_clk *imc;
+ struct clk *clk;
+ int i;
+
+ if (id > 3) {
+ pr_crit("no more than 4 LMs can be attached\n");
+ return;
+ }
+ imc = &impd1_clks[id];
+
+ clk = icst_clk_register(NULL, &impd1_icst1_desc, base);
+ imc->vcoclk = clk;
+ imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
+
+ /* UART reference clock */
+ clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+ 14745600);
+ imc->uartclk = clk;
+ imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
+ imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
+
+ for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+ clkdev_add(imc->clks[i]);
+}
+
+void integrator_impd1_clk_exit(unsigned int id)
+{
+ int i;
+ struct impd1_clk *imc;
+
+ if (id > 3)
+ return;
+ imc = &impd1_clks[id];
+
+ for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+ clkdev_drop(imc->clks[i]);
+ clk_unregister(imc->uartclk);
+ clk_unregister(imc->vcoclk);
+}
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
index a5053921bf7f..08593b4ee2c9 100644
--- a/drivers/clk/versatile/clk-integrator.c
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -1,8 +1,16 @@
+/*
+ * Clock driver for the ARM Integrator/AP and Integrator/CP boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can 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/clk-provider.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk-provider.h>
+#include <linux/platform_data/clk-integrator.h>
#include <mach/hardware.h>
#include <mach/platform.h>
@@ -14,42 +22,6 @@
* Inspired by portions of:
* plat-versatile/clock.c and plat-versatile/include/plat/clock.h
*/
-#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
-#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
-
-/**
- * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
- * @vco: ICST VCO parameters to update with hardware status
- */
-static struct icst_vco cp_auxvco_get(void)
-{
- u32 val;
- struct icst_vco vco;
-
- val = readl(CM_AUXOSC);
- vco.v = val & 0x1ff;
- vco.r = (val >> 9) & 0x7f;
- vco.s = (val >> 16) & 03;
- return vco;
-}
-
-/**
- * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
- * @vco: ICST VCO parameters to commit
- */
-static void cp_auxvco_set(struct icst_vco vco)
-{
- u32 val;
-
- val = readl(CM_AUXOSC) & ~0x7ffff;
- val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
- /* This magic unlocks the CM VCO so it can be controlled */
- writel(0xa05f, CM_LOCK);
- writel(val, CM_AUXOSC);
- /* This locks the CM again */
- writel(0, CM_LOCK);
-}
static const struct icst_params cp_auxvco_params = {
.ref = 24000000,
@@ -65,8 +37,8 @@ static const struct icst_params cp_auxvco_params = {
static const struct clk_icst_desc __initdata cp_icst_desc = {
.params = &cp_auxvco_params,
- .getvco = cp_auxvco_get,
- .setvco = cp_auxvco_set,
+ .vco_offset = 0x1c,
+ .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
};
/*
@@ -106,6 +78,7 @@ void __init integrator_clk_init(bool is_cp)
clk_register_clkdev(clk, NULL, "sp804");
/* ICST VCO clock used on the Integrator/CP CLCD */
- clk = icst_clk_register(NULL, &cp_icst_desc);
+ clk = icst_clk_register(NULL, &cp_icst_desc,
+ __io_address(INTEGRATOR_HDR_BASE));
clk_register_clkdev(clk, NULL, "clcd");
}
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
index e21a99cef378..cda07e70a408 100644
--- a/drivers/clk/versatile/clk-realview.c
+++ b/drivers/clk/versatile/clk-realview.c
@@ -1,3 +1,11 @@
+/*
+ * Clock driver for the ARM RealView boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * This program is free software; you can 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/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
@@ -13,38 +21,6 @@
* Implementation of the ARM RealView clock trees.
*/
-static void __iomem *sys_lock;
-static void __iomem *sys_vcoreg;
-
-/**
- * realview_oscvco_get() - get ICST OSC settings for the RealView
- */
-static struct icst_vco realview_oscvco_get(void)
-{
- u32 val;
- struct icst_vco vco;
-
- val = readl(sys_vcoreg);
- vco.v = val & 0x1ff;
- vco.r = (val >> 9) & 0x7f;
- vco.s = (val >> 16) & 03;
- return vco;
-}
-
-static void realview_oscvco_set(struct icst_vco vco)
-{
- u32 val;
-
- val = readl(sys_vcoreg) & ~0x7ffff;
- val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
- /* This magic unlocks the CM VCO so it can be controlled */
- writel(0xa05f, sys_lock);
- writel(val, sys_vcoreg);
- /* This locks the CM again */
- writel(0, sys_lock);
-}
-
static const struct icst_params realview_oscvco_params = {
.ref = 24000000,
.vco_max = ICST307_VCO_MAX,
@@ -57,10 +33,16 @@ static const struct icst_params realview_oscvco_params = {
.idx2s = icst307_idx2s,
};
-static const struct clk_icst_desc __initdata realview_icst_desc = {
+static const struct clk_icst_desc __initdata realview_osc0_desc = {
+ .params = &realview_oscvco_params,
+ .vco_offset = REALVIEW_SYS_OSC0_OFFSET,
+ .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
+};
+
+static const struct clk_icst_desc __initdata realview_osc4_desc = {
.params = &realview_oscvco_params,
- .getvco = realview_oscvco_get,
- .setvco = realview_oscvco_set,
+ .vco_offset = REALVIEW_SYS_OSC4_OFFSET,
+ .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
};
/*
@@ -70,13 +52,6 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
{
struct clk *clk;
- sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET;
- if (is_pb1176)
- sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET;
- else
- sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET;
-
-
/* APB clock dummy */
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
clk_register_clkdev(clk, "apb_pclk", NULL);
@@ -108,7 +83,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
clk_register_clkdev(clk, NULL, "sp804");
/* ICST VCO clock */
- clk = icst_clk_register(NULL, &realview_icst_desc);
+ if (is_pb1176)
+ clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase);
+ else
+ clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase);
+
clk_register_clkdev(clk, NULL, "dev:clcd");
clk_register_clkdev(clk, NULL, "issp:clcd");
}
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
new file mode 100644
index 000000000000..dcb6ae0a0425
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -0,0 +1,146 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define pr_fmt(fmt) "vexpress-osc: " fmt
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/vexpress.h>
+
+struct vexpress_osc {
+ struct vexpress_config_func *func;
+ struct clk_hw hw;
+ unsigned long rate_min;
+ unsigned long rate_max;
+};
+
+#define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw)
+
+static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct vexpress_osc *osc = to_vexpress_osc(hw);
+ u32 rate;
+
+ vexpress_config_read(osc->func, 0, &rate);
+
+ return rate;
+}
+
+static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+ if (WARN_ON(osc->rate_min && rate < osc->rate_min))
+ rate = osc->rate_min;
+
+ if (WARN_ON(osc->rate_max && rate > osc->rate_max))
+ rate = osc->rate_max;
+
+ return rate;
+}
+
+static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+ return vexpress_config_write(osc->func, 0, rate);
+}
+
+static struct clk_ops vexpress_osc_ops = {
+ .recalc_rate = vexpress_osc_recalc_rate,
+ .round_rate = vexpress_osc_round_rate,
+ .set_rate = vexpress_osc_set_rate,
+};
+
+
+struct clk * __init vexpress_osc_setup(struct device *dev)
+{
+ struct clk_init_data init;
+ struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+
+ if (!osc)
+ return NULL;
+
+ osc->func = vexpress_config_func_get_by_dev(dev);
+ if (!osc->func) {
+ kfree(osc);
+ return NULL;
+ }
+
+ init.name = dev_name(dev);
+ init.ops = &vexpress_osc_ops;
+ init.flags = CLK_IS_ROOT;
+ init.num_parents = 0;
+ osc->hw.init = &init;
+
+ return clk_register(NULL, &osc->hw);
+}
+
+void __init vexpress_osc_of_setup(struct device_node *node)
+{
+ struct clk_init_data init;
+ struct vexpress_osc *osc;
+ struct clk *clk;
+ u32 range[2];
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ goto error;
+
+ osc->func = vexpress_config_func_get_by_node(node);
+ if (!osc->func) {
+ pr_err("Failed to obtain config func for node '%s'!\n",
+ node->name);
+ goto error;
+ }
+
+ if (of_property_read_u32_array(node, "freq-range", range,
+ ARRAY_SIZE(range)) == 0) {
+ osc->rate_min = range[0];
+ osc->rate_max = range[1];
+ }
+
+ of_property_read_string(node, "clock-output-names", &init.name);
+ if (!init.name)
+ init.name = node->name;
+
+ init.ops = &vexpress_osc_ops;
+ init.flags = CLK_IS_ROOT;
+ init.num_parents = 0;
+
+ osc->hw.init = &init;
+
+ clk = clk_register(NULL, &osc->hw);
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clock '%s'!\n", init.name);
+ goto error;
+ }
+
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+ pr_debug("Registered clock '%s'\n", init.name);
+
+ return;
+
+error:
+ if (osc->func)
+ vexpress_config_func_put(osc->func);
+ kfree(osc);
+}
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c
new file mode 100644
index 000000000000..c742ac7c60bb
--- /dev/null
+++ b/drivers/clk/versatile/clk-vexpress.c
@@ -0,0 +1,142 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+
+#include <asm/hardware/sp810.h>
+
+static struct clk *vexpress_sp810_timerclken[4];
+static DEFINE_SPINLOCK(vexpress_sp810_lock);
+
+static void __init vexpress_sp810_init(void __iomem *base)
+{
+ int i;
+
+ if (WARN_ON(!base))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
+ char name[12];
+ const char *parents[] = {
+ "v2m:refclk32khz", /* REFCLK */
+ "v2m:refclk1mhz" /* TIMCLK */
+ };
+
+ snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
+
+ vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
+ parents, 2, 0, base + SCCTRL,
+ SCCTRL_TIMERENnSEL_SHIFT(i), 1,
+ 0, &vexpress_sp810_lock);
+
+ if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
+ break;
+ }
+}
+
+
+static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
+ "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
+ "mb:mmci", "mb:kmi0", "mb:kmi1"
+};
+
+void __init vexpress_clk_init(void __iomem *sp810_base)
+{
+ struct clk *clk;
+ int i;
+
+ clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
+ CLK_IS_ROOT, 0);
+ WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
+
+ clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
+ CLK_IS_ROOT, 24000000);
+ for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
+ WARN_ON(clk_register_clkdev(clk, NULL,
+ vexpress_clk_24mhz_periphs[i]));
+
+ clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
+ CLK_IS_ROOT, 32768);
+ WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
+
+ clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
+ CLK_IS_ROOT, 1000000);
+
+ vexpress_sp810_init(sp810_base);
+
+ for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+ WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
+
+ WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+ "v2m-timer0", "sp804"));
+ WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+ "v2m-timer1", "sp804"));
+}
+
+#if defined(CONFIG_OF)
+
+struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
+{
+ if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
+ ARRAY_SIZE(vexpress_sp810_timerclken)))
+ return NULL;
+
+ return vexpress_sp810_timerclken[clkspec->args[0]];
+}
+
+static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
+ {}
+};
+
+void __init vexpress_clk_of_init(void)
+{
+ struct device_node *node;
+ struct clk *clk;
+ struct clk *refclk, *timclk;
+
+ of_clk_init(vexpress_fixed_clk_match);
+
+ node = of_find_compatible_node(NULL, NULL, "arm,sp810");
+ vexpress_sp810_init(of_iomap(node, 0));
+ of_clk_add_provider(node, vexpress_sp810_of_get, NULL);
+
+ /* Select "better" (faster) parent for SP804 timers */
+ refclk = of_clk_get_by_name(node, "refclk");
+ timclk = of_clk_get_by_name(node, "timclk");
+ if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) {
+ int i = 0;
+
+ if (clk_get_rate(refclk) > clk_get_rate(timclk))
+ clk = refclk;
+ else
+ clk = timclk;
+
+ for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+ WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i],
+ clk));
+ }
+
+ WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+ "v2m-timer0", "sp804"));
+ WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+ "v2m-timer1", "sp804"));
+}
+
+#endif
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 5961e6415f08..a0b3661d90b0 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -76,3 +76,10 @@ config ARM_EXYNOS5250_CPUFREQ
help
This adds the CPUFreq driver for Samsung EXYNOS5250
SoC.
+
+config ARM_SPEAR_CPUFREQ
+ bool "SPEAr CPUFreq support"
+ depends on PLAT_SPEAR
+ default y
+ help
+ This adds the CPUFreq driver support for SPEAr SOCs.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 1bc90e1306d8..1f254ec087c1 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -7,8 +7,8 @@ obj-$(CONFIG_CPU_FREQ_STAT) += cpufreq_stats.o
obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
-obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o cpufreq_governor.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
+obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
##################################################################################
# PowerPC platform drivers
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index e9158278c71d..52bf36d599f5 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -174,7 +174,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
.attr = cpu0_cpufreq_attr,
};
-static int __devinit cpu0_cpufreq_driver_init(void)
+static int cpu0_cpufreq_driver_init(void)
{
struct device_node *np;
int ret;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index fb8a5279c5d8..1f93dbd72355 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -15,6 +15,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -127,7 +129,7 @@ static int __init init_cpufreq_transition_notifier_list(void)
pure_initcall(init_cpufreq_transition_notifier_list);
static int off __read_mostly;
-int cpufreq_disabled(void)
+static int cpufreq_disabled(void)
{
return off;
}
@@ -402,7 +404,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
static ssize_t store_##file_name \
(struct cpufreq_policy *policy, const char *buf, size_t count) \
{ \
- unsigned int ret = -EINVAL; \
+ unsigned int ret; \
struct cpufreq_policy new_policy; \
\
ret = cpufreq_get_policy(&new_policy, policy->cpu); \
@@ -445,7 +447,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
return sprintf(buf, "performance\n");
else if (policy->governor)
- return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n",
+ return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n",
policy->governor->name);
return -EINVAL;
}
@@ -457,7 +459,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
const char *buf, size_t count)
{
- unsigned int ret = -EINVAL;
+ unsigned int ret;
char str_governor[16];
struct cpufreq_policy new_policy;
@@ -491,7 +493,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
*/
static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf)
{
- return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name);
+ return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name);
}
/**
@@ -512,7 +514,7 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
- (CPUFREQ_NAME_LEN + 2)))
goto out;
- i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
+ i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
}
out:
i += sprintf(&buf[i], "\n");
@@ -581,7 +583,7 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf)
}
/**
- * show_scaling_driver - show the current cpufreq HW/BIOS limitation
+ * show_bios_limit - show the current cpufreq HW/BIOS limitation
*/
static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf)
{
@@ -1468,12 +1470,23 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int relation)
{
int retval = -EINVAL;
+ unsigned int old_target_freq = target_freq;
if (cpufreq_disabled())
return -ENODEV;
- pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
- target_freq, relation);
+ /* Make sure that target_freq is within supported range */
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+
+ pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
+ policy->cpu, target_freq, relation, old_target_freq);
+
+ if (target_freq == policy->cur)
+ return 0;
+
if (cpu_online(policy->cpu) && cpufreq_driver->target)
retval = cpufreq_driver->target(policy, target_freq, relation);
@@ -1509,12 +1522,14 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
{
int ret = 0;
+ if (!(cpu_online(cpu) && cpufreq_driver->getavg))
+ return 0;
+
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
return -EINVAL;
- if (cpu_online(cpu) && cpufreq_driver->getavg)
- ret = cpufreq_driver->getavg(policy, cpu);
+ ret = cpufreq_driver->getavg(policy, cpu);
cpufreq_cpu_put(policy);
return ret;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index a152af7e1991..64ef737e7e72 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -11,83 +11,30 @@
* published by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
+/* Conservative governor macors */
#define DEF_FREQUENCY_UP_THRESHOLD (80)
#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO (2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER (1000)
-#define MIN_LATENCY_MULTIPLIER (100)
#define DEF_SAMPLING_DOWN_FACTOR (1)
#define MAX_SAMPLING_DOWN_FACTOR (10)
-#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-
-struct cpu_dbs_info_s {
- cputime64_t prev_cpu_idle;
- cputime64_t prev_cpu_wall;
- cputime64_t prev_cpu_nice;
- struct cpufreq_policy *cur_policy;
- struct delayed_work work;
- unsigned int down_skip;
- unsigned int requested_freq;
- int cpu;
- unsigned int enable:1;
- /*
- * percpu mutex that serializes governor limit change with
- * do_dbs_timer invocation. We do not want do_dbs_timer to run
- * when user is changing the governor or limits.
- */
- struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, cs_cpu_dbs_info);
-static unsigned int dbs_enable; /* number of CPUs using this policy */
+static struct dbs_data cs_dbs_data;
+static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
- unsigned int sampling_rate;
- unsigned int sampling_down_factor;
- unsigned int up_threshold;
- unsigned int down_threshold;
- unsigned int ignore_nice;
- unsigned int freq_step;
-} dbs_tuners_ins = {
+static struct cs_dbs_tuners cs_tuners = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
@@ -95,95 +42,121 @@ static struct dbs_tuners {
.freq_step = 5,
};
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate *
+ * sampling_down_factor, we check, if current idle time is more than 80%, then
+ * we try to decrease frequency
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of maximum frequency
+ */
+static void cs_check_cpu(int cpu, unsigned int load)
{
- u64 idle_time;
- u64 cur_wall_time;
- u64 busy_time;
+ struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
+ struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+ unsigned int freq_target;
+
+ /*
+ * break out if we 'cannot' reduce the speed as the user might
+ * want freq_step to be zero
+ */
+ if (cs_tuners.freq_step == 0)
+ return;
- cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+ /* Check for frequency increase */
+ if (load > cs_tuners.up_threshold) {
+ dbs_info->down_skip = 0;
- busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+ /* if we are already at full speed then break out early */
+ if (dbs_info->requested_freq == policy->max)
+ return;
- idle_time = cur_wall_time - busy_time;
- if (wall)
- *wall = jiffies_to_usecs(cur_wall_time);
+ freq_target = (cs_tuners.freq_step * policy->max) / 100;
- return jiffies_to_usecs(idle_time);
+ /* max freq cannot be less than 100. But who knows.... */
+ if (unlikely(freq_target == 0))
+ freq_target = 5;
+
+ dbs_info->requested_freq += freq_target;
+ if (dbs_info->requested_freq > policy->max)
+ dbs_info->requested_freq = policy->max;
+
+ __cpufreq_driver_target(policy, dbs_info->requested_freq,
+ CPUFREQ_RELATION_H);
+ return;
+ }
+
+ /*
+ * The optimal frequency is the frequency that is the lowest that can
+ * support the current CPU usage without triggering the up policy. To be
+ * safe, we focus 10 points under the threshold.
+ */
+ if (load < (cs_tuners.down_threshold - 10)) {
+ freq_target = (cs_tuners.freq_step * policy->max) / 100;
+
+ dbs_info->requested_freq -= freq_target;
+ if (dbs_info->requested_freq < policy->min)
+ dbs_info->requested_freq = policy->min;
+
+ /*
+ * if we cannot reduce the frequency anymore, break out early
+ */
+ if (policy->cur == policy->min)
+ return;
+
+ __cpufreq_driver_target(policy, dbs_info->requested_freq,
+ CPUFREQ_RELATION_H);
+ return;
+ }
}
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void cs_dbs_timer(struct work_struct *work)
{
- u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+ struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
+ struct cs_cpu_dbs_info_s, cdbs.work.work);
+ unsigned int cpu = dbs_info->cdbs.cpu;
+ int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
- if (idle_time == -1ULL)
- return get_cpu_idle_time_jiffy(cpu, wall);
- else
- idle_time += get_cpu_iowait_time_us(cpu, wall);
+ mutex_lock(&dbs_info->cdbs.timer_mutex);
- return idle_time;
+ dbs_check_cpu(&cs_dbs_data, cpu);
+
+ schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+ mutex_unlock(&dbs_info->cdbs.timer_mutex);
}
-/* keep track of frequency transitions */
-static int
-dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
- void *data)
+static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
{
struct cpufreq_freqs *freq = data;
- struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cs_cpu_dbs_info,
- freq->cpu);
-
+ struct cs_cpu_dbs_info_s *dbs_info =
+ &per_cpu(cs_cpu_dbs_info, freq->cpu);
struct cpufreq_policy *policy;
- if (!this_dbs_info->enable)
+ if (!dbs_info->enable)
return 0;
- policy = this_dbs_info->cur_policy;
+ policy = dbs_info->cdbs.cur_policy;
/*
- * we only care if our internally tracked freq moves outside
- * the 'valid' ranges of freqency available to us otherwise
- * we do not change it
+ * we only care if our internally tracked freq moves outside the 'valid'
+ * ranges of freqency available to us otherwise we do not change it
*/
- if (this_dbs_info->requested_freq > policy->max
- || this_dbs_info->requested_freq < policy->min)
- this_dbs_info->requested_freq = freq->new;
+ if (dbs_info->requested_freq > policy->max
+ || dbs_info->requested_freq < policy->min)
+ dbs_info->requested_freq = freq->new;
return 0;
}
-static struct notifier_block dbs_cpufreq_notifier_block = {
- .notifier_call = dbs_cpufreq_notifier
-};
-
/************************** sysfs interface ************************/
static ssize_t show_sampling_rate_min(struct kobject *kobj,
struct attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", min_sampling_rate);
+ return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
}
-define_one_global_ro(sampling_rate_min);
-
-/* cpufreq_conservative Governor Tunables */
-#define show_one(file_name, object) \
-static ssize_t show_##file_name \
-(struct kobject *kobj, struct attribute *attr, char *buf) \
-{ \
- return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
-}
-show_one(sampling_rate, sampling_rate);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
-show_one(ignore_nice_load, ignore_nice);
-show_one(freq_step, freq_step);
-
static ssize_t store_sampling_down_factor(struct kobject *a,
struct attribute *b,
const char *buf, size_t count)
@@ -195,7 +168,7 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
return -EINVAL;
- dbs_tuners_ins.sampling_down_factor = input;
+ cs_tuners.sampling_down_factor = input;
return count;
}
@@ -209,7 +182,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
- dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
+ cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
return count;
}
@@ -220,11 +193,10 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
int ret;
ret = sscanf(buf, "%u", &input);
- if (ret != 1 || input > 100 ||
- input <= dbs_tuners_ins.down_threshold)
+ if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
return -EINVAL;
- dbs_tuners_ins.up_threshold = input;
+ cs_tuners.up_threshold = input;
return count;
}
@@ -237,21 +209,19 @@ static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
/* cannot be lower than 11 otherwise freq will not fall */
if (ret != 1 || input < 11 || input > 100 ||
- input >= dbs_tuners_ins.up_threshold)
+ input >= cs_tuners.up_threshold)
return -EINVAL;
- dbs_tuners_ins.down_threshold = input;
+ cs_tuners.down_threshold = input;
return count;
}
static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
- unsigned int input;
+ unsigned int input, j;
int ret;
- unsigned int j;
-
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
@@ -259,19 +229,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
if (input > 1)
input = 1;
- if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
+ if (input == cs_tuners.ignore_nice) /* nothing to do */
return count;
- dbs_tuners_ins.ignore_nice = input;
+ cs_tuners.ignore_nice = input;
/* we need to re-evaluate prev_cpu_idle */
for_each_online_cpu(j) {
- struct cpu_dbs_info_s *dbs_info;
+ struct cs_cpu_dbs_info_s *dbs_info;
dbs_info = &per_cpu(cs_cpu_dbs_info, j);
- dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
- &dbs_info->prev_cpu_wall);
- if (dbs_tuners_ins.ignore_nice)
- dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+ dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+ &dbs_info->cdbs.prev_cpu_wall);
+ if (cs_tuners.ignore_nice)
+ dbs_info->cdbs.prev_cpu_nice =
+ kcpustat_cpu(j).cpustat[CPUTIME_NICE];
}
return count;
}
@@ -289,18 +260,28 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
if (input > 100)
input = 100;
- /* no need to test here if freq_step is zero as the user might actually
- * want this, they would be crazy though :) */
- dbs_tuners_ins.freq_step = input;
+ /*
+ * no need to test here if freq_step is zero as the user might actually
+ * want this, they would be crazy though :)
+ */
+ cs_tuners.freq_step = input;
return count;
}
+show_one(cs, sampling_rate, sampling_rate);
+show_one(cs, sampling_down_factor, sampling_down_factor);
+show_one(cs, up_threshold, up_threshold);
+show_one(cs, down_threshold, down_threshold);
+show_one(cs, ignore_nice_load, ignore_nice);
+show_one(cs, freq_step, freq_step);
+
define_one_global_rw(sampling_rate);
define_one_global_rw(sampling_down_factor);
define_one_global_rw(up_threshold);
define_one_global_rw(down_threshold);
define_one_global_rw(ignore_nice_load);
define_one_global_rw(freq_step);
+define_one_global_ro(sampling_rate_min);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -313,283 +294,38 @@ static struct attribute *dbs_attributes[] = {
NULL
};
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group cs_attr_group = {
.attrs = dbs_attributes,
.name = "conservative",
};
/************************** sysfs end ************************/
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
- unsigned int load = 0;
- unsigned int max_load = 0;
- unsigned int freq_target;
-
- struct cpufreq_policy *policy;
- unsigned int j;
-
- policy = this_dbs_info->cur_policy;
-
- /*
- * Every sampling_rate, we check, if current idle time is less
- * than 20% (default), then we try to increase frequency
- * Every sampling_rate*sampling_down_factor, we check, if current
- * idle time is more than 80%, then we try to decrease frequency
- *
- * Any frequency increase takes it to the maximum frequency.
- * Frequency reduction happens at minimum steps of
- * 5% (default) of maximum frequency
- */
-
- /* Get Absolute Load */
- for_each_cpu(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
- cputime64_t cur_wall_time, cur_idle_time;
- unsigned int idle_time, wall_time;
-
- j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-
- cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-
- wall_time = (unsigned int)
- (cur_wall_time - j_dbs_info->prev_cpu_wall);
- j_dbs_info->prev_cpu_wall = cur_wall_time;
-
- idle_time = (unsigned int)
- (cur_idle_time - j_dbs_info->prev_cpu_idle);
- j_dbs_info->prev_cpu_idle = cur_idle_time;
-
- if (dbs_tuners_ins.ignore_nice) {
- u64 cur_nice;
- unsigned long cur_nice_jiffies;
-
- cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
- j_dbs_info->prev_cpu_nice;
- /*
- * Assumption: nice time between sampling periods will
- * be less than 2^32 jiffies for 32 bit sys
- */
- cur_nice_jiffies = (unsigned long)
- cputime64_to_jiffies64(cur_nice);
-
- j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
- idle_time += jiffies_to_usecs(cur_nice_jiffies);
- }
+define_get_cpu_dbs_routines(cs_cpu_dbs_info);
- if (unlikely(!wall_time || wall_time < idle_time))
- continue;
-
- load = 100 * (wall_time - idle_time) / wall_time;
-
- if (load > max_load)
- max_load = load;
- }
-
- /*
- * break out if we 'cannot' reduce the speed as the user might
- * want freq_step to be zero
- */
- if (dbs_tuners_ins.freq_step == 0)
- return;
-
- /* Check for frequency increase */
- if (max_load > dbs_tuners_ins.up_threshold) {
- this_dbs_info->down_skip = 0;
-
- /* if we are already at full speed then break out early */
- if (this_dbs_info->requested_freq == policy->max)
- return;
-
- freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
- /* max freq cannot be less than 100. But who knows.... */
- if (unlikely(freq_target == 0))
- freq_target = 5;
-
- this_dbs_info->requested_freq += freq_target;
- if (this_dbs_info->requested_freq > policy->max)
- this_dbs_info->requested_freq = policy->max;
-
- __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
- CPUFREQ_RELATION_H);
- return;
- }
-
- /*
- * The optimal frequency is the frequency that is the lowest that
- * can support the current CPU usage without triggering the up
- * policy. To be safe, we focus 10 points under the threshold.
- */
- if (max_load < (dbs_tuners_ins.down_threshold - 10)) {
- freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
- this_dbs_info->requested_freq -= freq_target;
- if (this_dbs_info->requested_freq < policy->min)
- this_dbs_info->requested_freq = policy->min;
-
- /*
- * if we cannot reduce the frequency anymore, break out early
- */
- if (policy->cur == policy->min)
- return;
-
- __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
- CPUFREQ_RELATION_H);
- return;
- }
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
- struct cpu_dbs_info_s *dbs_info =
- container_of(work, struct cpu_dbs_info_s, work.work);
- unsigned int cpu = dbs_info->cpu;
-
- /* We want all CPUs to do sampling nearly on same jiffy */
- int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
- delay -= jiffies % delay;
-
- mutex_lock(&dbs_info->timer_mutex);
-
- dbs_check_cpu(dbs_info);
-
- schedule_delayed_work_on(cpu, &dbs_info->work, delay);
- mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
- /* We want all CPUs to do sampling nearly on same jiffy */
- int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
- delay -= jiffies % delay;
+static struct notifier_block cs_cpufreq_notifier_block = {
+ .notifier_call = dbs_cpufreq_notifier,
+};
- dbs_info->enable = 1;
- INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
- schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct cs_ops cs_ops = {
+ .notifier_block = &cs_cpufreq_notifier_block,
+};
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
-{
- dbs_info->enable = 0;
- cancel_delayed_work_sync(&dbs_info->work);
-}
+static struct dbs_data cs_dbs_data = {
+ .governor = GOV_CONSERVATIVE,
+ .attr_group = &cs_attr_group,
+ .tuners = &cs_tuners,
+ .get_cpu_cdbs = get_cpu_cdbs,
+ .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+ .gov_dbs_timer = cs_dbs_timer,
+ .gov_check_cpu = cs_check_cpu,
+ .gov_ops = &cs_ops,
+};
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
unsigned int event)
{
- unsigned int cpu = policy->cpu;
- struct cpu_dbs_info_s *this_dbs_info;
- unsigned int j;
- int rc;
-
- this_dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
-
- switch (event) {
- case CPUFREQ_GOV_START:
- if ((!cpu_online(cpu)) || (!policy->cur))
- return -EINVAL;
-
- mutex_lock(&dbs_mutex);
-
- for_each_cpu(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
- j_dbs_info->cur_policy = policy;
-
- j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
- &j_dbs_info->prev_cpu_wall);
- if (dbs_tuners_ins.ignore_nice)
- j_dbs_info->prev_cpu_nice =
- kcpustat_cpu(j).cpustat[CPUTIME_NICE];
- }
- this_dbs_info->cpu = cpu;
- this_dbs_info->down_skip = 0;
- this_dbs_info->requested_freq = policy->cur;
-
- mutex_init(&this_dbs_info->timer_mutex);
- dbs_enable++;
- /*
- * Start the timerschedule work, when this governor
- * is used for first time
- */
- if (dbs_enable == 1) {
- unsigned int latency;
- /* policy latency is in nS. Convert it to uS first */
- latency = policy->cpuinfo.transition_latency / 1000;
- if (latency == 0)
- latency = 1;
-
- rc = sysfs_create_group(cpufreq_global_kobject,
- &dbs_attr_group);
- if (rc) {
- mutex_unlock(&dbs_mutex);
- return rc;
- }
-
- /*
- * conservative does not implement micro like ondemand
- * governor, thus we are bound to jiffes/HZ
- */
- min_sampling_rate =
- MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
- /* Bring kernel and HW constraints together */
- min_sampling_rate = max(min_sampling_rate,
- MIN_LATENCY_MULTIPLIER * latency);
- dbs_tuners_ins.sampling_rate =
- max(min_sampling_rate,
- latency * LATENCY_MULTIPLIER);
-
- cpufreq_register_notifier(
- &dbs_cpufreq_notifier_block,
- CPUFREQ_TRANSITION_NOTIFIER);
- }
- mutex_unlock(&dbs_mutex);
-
- dbs_timer_init(this_dbs_info);
-
- break;
-
- case CPUFREQ_GOV_STOP:
- dbs_timer_exit(this_dbs_info);
-
- mutex_lock(&dbs_mutex);
- dbs_enable--;
- mutex_destroy(&this_dbs_info->timer_mutex);
-
- /*
- * Stop the timerschedule work, when this governor
- * is used for first time
- */
- if (dbs_enable == 0)
- cpufreq_unregister_notifier(
- &dbs_cpufreq_notifier_block,
- CPUFREQ_TRANSITION_NOTIFIER);
-
- mutex_unlock(&dbs_mutex);
- if (!dbs_enable)
- sysfs_remove_group(cpufreq_global_kobject,
- &dbs_attr_group);
-
- break;
-
- case CPUFREQ_GOV_LIMITS:
- mutex_lock(&this_dbs_info->timer_mutex);
- if (policy->max < this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(
- this_dbs_info->cur_policy,
- policy->max, CPUFREQ_RELATION_H);
- else if (policy->min > this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(
- this_dbs_info->cur_policy,
- policy->min, CPUFREQ_RELATION_L);
- dbs_check_cpu(this_dbs_info);
- mutex_unlock(&this_dbs_info->timer_mutex);
-
- break;
- }
- return 0;
+ return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
}
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
@@ -597,13 +333,14 @@ static
#endif
struct cpufreq_governor cpufreq_gov_conservative = {
.name = "conservative",
- .governor = cpufreq_governor_dbs,
+ .governor = cs_cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
};
static int __init cpufreq_gov_dbs_init(void)
{
+ mutex_init(&cs_dbs_data.mutex);
return cpufreq_register_governor(&cpufreq_gov_conservative);
}
@@ -612,7 +349,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
cpufreq_unregister_governor(&cpufreq_gov_conservative);
}
-
MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
"Low Latency Frequency Transition capable processors "
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
new file mode 100644
index 000000000000..6c5f1d383cdc
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -0,0 +1,318 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.c
+ *
+ * CPUFREQ governors common code
+ *
+ * Copyright (C) 2001 Russell King
+ * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ * (C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ * (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ * (c) 2012 Viresh Kumar <viresh.kumar@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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/cputime.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/export.h>
+#include <linux/kernel_stat.h>
+#include <linux/mutex.h>
+#include <linux/tick.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "cpufreq_governor.h"
+
+static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+{
+ u64 idle_time;
+ u64 cur_wall_time;
+ u64 busy_time;
+
+ cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+
+ busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
+ busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
+ busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
+ busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
+ busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
+ busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+
+ idle_time = cur_wall_time - busy_time;
+ if (wall)
+ *wall = cputime_to_usecs(cur_wall_time);
+
+ return cputime_to_usecs(idle_time);
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall)
+{
+ u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+
+ if (idle_time == -1ULL)
+ return get_cpu_idle_time_jiffy(cpu, wall);
+ else
+ idle_time += get_cpu_iowait_time_us(cpu, wall);
+
+ return idle_time;
+}
+EXPORT_SYMBOL_GPL(get_cpu_idle_time);
+
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
+{
+ struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+ struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+ struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+ struct cpufreq_policy *policy;
+ unsigned int max_load = 0;
+ unsigned int ignore_nice;
+ unsigned int j;
+
+ if (dbs_data->governor == GOV_ONDEMAND)
+ ignore_nice = od_tuners->ignore_nice;
+ else
+ ignore_nice = cs_tuners->ignore_nice;
+
+ policy = cdbs->cur_policy;
+
+ /* Get Absolute Load (in terms of freq for ondemand gov) */
+ for_each_cpu(j, policy->cpus) {
+ struct cpu_dbs_common_info *j_cdbs;
+ u64 cur_wall_time, cur_idle_time, cur_iowait_time;
+ unsigned int idle_time, wall_time, iowait_time;
+ unsigned int load;
+
+ j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+ cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+ wall_time = (unsigned int)
+ (cur_wall_time - j_cdbs->prev_cpu_wall);
+ j_cdbs->prev_cpu_wall = cur_wall_time;
+
+ idle_time = (unsigned int)
+ (cur_idle_time - j_cdbs->prev_cpu_idle);
+ j_cdbs->prev_cpu_idle = cur_idle_time;
+
+ if (ignore_nice) {
+ u64 cur_nice;
+ unsigned long cur_nice_jiffies;
+
+ cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
+ cdbs->prev_cpu_nice;
+ /*
+ * Assumption: nice time between sampling periods will
+ * be less than 2^32 jiffies for 32 bit sys
+ */
+ cur_nice_jiffies = (unsigned long)
+ cputime64_to_jiffies64(cur_nice);
+
+ cdbs->prev_cpu_nice =
+ kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+ idle_time += jiffies_to_usecs(cur_nice_jiffies);
+ }
+
+ if (dbs_data->governor == GOV_ONDEMAND) {
+ struct od_cpu_dbs_info_s *od_j_dbs_info =
+ dbs_data->get_cpu_dbs_info_s(cpu);
+
+ cur_iowait_time = get_cpu_iowait_time_us(j,
+ &cur_wall_time);
+ if (cur_iowait_time == -1ULL)
+ cur_iowait_time = 0;
+
+ iowait_time = (unsigned int) (cur_iowait_time -
+ od_j_dbs_info->prev_cpu_iowait);
+ od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
+
+ /*
+ * For the purpose of ondemand, waiting for disk IO is
+ * an indication that you're performance critical, and
+ * not that the system is actually idle. So subtract the
+ * iowait time from the cpu idle time.
+ */
+ if (od_tuners->io_is_busy && idle_time >= iowait_time)
+ idle_time -= iowait_time;
+ }
+
+ if (unlikely(!wall_time || wall_time < idle_time))
+ continue;
+
+ load = 100 * (wall_time - idle_time) / wall_time;
+
+ if (dbs_data->governor == GOV_ONDEMAND) {
+ int freq_avg = __cpufreq_driver_getavg(policy, j);
+ if (freq_avg <= 0)
+ freq_avg = policy->cur;
+
+ load *= freq_avg;
+ }
+
+ if (load > max_load)
+ max_load = load;
+ }
+
+ dbs_data->gov_check_cpu(cpu, max_load);
+}
+EXPORT_SYMBOL_GPL(dbs_check_cpu);
+
+static inline void dbs_timer_init(struct dbs_data *dbs_data,
+ struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate)
+{
+ int delay = delay_for_sampling_rate(sampling_rate);
+
+ INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer);
+ schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
+}
+
+static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
+{
+ cancel_delayed_work_sync(&cdbs->work);
+}
+
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+ struct cpufreq_policy *policy, unsigned int event)
+{
+ struct od_cpu_dbs_info_s *od_dbs_info = NULL;
+ struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
+ struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+ struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+ struct cpu_dbs_common_info *cpu_cdbs;
+ unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+ int rc;
+
+ cpu_cdbs = dbs_data->get_cpu_cdbs(cpu);
+
+ if (dbs_data->governor == GOV_CONSERVATIVE) {
+ cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+ sampling_rate = &cs_tuners->sampling_rate;
+ ignore_nice = cs_tuners->ignore_nice;
+ } else {
+ od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+ sampling_rate = &od_tuners->sampling_rate;
+ ignore_nice = od_tuners->ignore_nice;
+ }
+
+ switch (event) {
+ case CPUFREQ_GOV_START:
+ if ((!cpu_online(cpu)) || (!policy->cur))
+ return -EINVAL;
+
+ mutex_lock(&dbs_data->mutex);
+
+ dbs_data->enable++;
+ cpu_cdbs->cpu = cpu;
+ for_each_cpu(j, policy->cpus) {
+ struct cpu_dbs_common_info *j_cdbs;
+ j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+ j_cdbs->cur_policy = policy;
+ j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
+ &j_cdbs->prev_cpu_wall);
+ if (ignore_nice)
+ j_cdbs->prev_cpu_nice =
+ kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+ }
+
+ /*
+ * Start the timerschedule work, when this governor is used for
+ * first time
+ */
+ if (dbs_data->enable != 1)
+ goto second_time;
+
+ rc = sysfs_create_group(cpufreq_global_kobject,
+ dbs_data->attr_group);
+ if (rc) {
+ mutex_unlock(&dbs_data->mutex);
+ return rc;
+ }
+
+ /* policy latency is in nS. Convert it to uS first */
+ latency = policy->cpuinfo.transition_latency / 1000;
+ if (latency == 0)
+ latency = 1;
+
+ /*
+ * conservative does not implement micro like ondemand
+ * governor, thus we are bound to jiffes/HZ
+ */
+ if (dbs_data->governor == GOV_CONSERVATIVE) {
+ struct cs_ops *ops = dbs_data->gov_ops;
+
+ cpufreq_register_notifier(ops->notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+
+ dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+ jiffies_to_usecs(10);
+ } else {
+ struct od_ops *ops = dbs_data->gov_ops;
+
+ od_tuners->io_is_busy = ops->io_busy();
+ }
+
+ /* Bring kernel and HW constraints together */
+ dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
+ MIN_LATENCY_MULTIPLIER * latency);
+ *sampling_rate = max(dbs_data->min_sampling_rate, latency *
+ LATENCY_MULTIPLIER);
+
+second_time:
+ if (dbs_data->governor == GOV_CONSERVATIVE) {
+ cs_dbs_info->down_skip = 0;
+ cs_dbs_info->enable = 1;
+ cs_dbs_info->requested_freq = policy->cur;
+ } else {
+ struct od_ops *ops = dbs_data->gov_ops;
+ od_dbs_info->rate_mult = 1;
+ od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+ ops->powersave_bias_init_cpu(cpu);
+ }
+ mutex_unlock(&dbs_data->mutex);
+
+ mutex_init(&cpu_cdbs->timer_mutex);
+ dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate);
+ break;
+
+ case CPUFREQ_GOV_STOP:
+ if (dbs_data->governor == GOV_CONSERVATIVE)
+ cs_dbs_info->enable = 0;
+
+ dbs_timer_exit(cpu_cdbs);
+
+ mutex_lock(&dbs_data->mutex);
+ mutex_destroy(&cpu_cdbs->timer_mutex);
+ dbs_data->enable--;
+ if (!dbs_data->enable) {
+ struct cs_ops *ops = dbs_data->gov_ops;
+
+ sysfs_remove_group(cpufreq_global_kobject,
+ dbs_data->attr_group);
+ if (dbs_data->governor == GOV_CONSERVATIVE)
+ cpufreq_unregister_notifier(ops->notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+ mutex_unlock(&dbs_data->mutex);
+
+ break;
+
+ case CPUFREQ_GOV_LIMITS:
+ mutex_lock(&cpu_cdbs->timer_mutex);
+ if (policy->max < cpu_cdbs->cur_policy->cur)
+ __cpufreq_driver_target(cpu_cdbs->cur_policy,
+ policy->max, CPUFREQ_RELATION_H);
+ else if (policy->min > cpu_cdbs->cur_policy->cur)
+ __cpufreq_driver_target(cpu_cdbs->cur_policy,
+ policy->min, CPUFREQ_RELATION_L);
+ dbs_check_cpu(dbs_data, cpu);
+ mutex_unlock(&cpu_cdbs->timer_mutex);
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
new file mode 100644
index 000000000000..f6616540c53d
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -0,0 +1,176 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.h
+ *
+ * Header file for CPUFreq governors common code
+ *
+ * Copyright (C) 2001 Russell King
+ * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ * (C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ * (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ * (c) 2012 Viresh Kumar <viresh.kumar@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.
+ */
+
+#ifndef _CPUFREQ_GOVERNER_H
+#define _CPUFREQ_GOVERNER_H
+
+#include <linux/cpufreq.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+
+/*
+ * The polling frequency depends on the capability of the processor. Default
+ * polling frequency is 1000 times the transition latency of the processor. The
+ * governor will work on any processor with transition latency <= 10mS, using
+ * appropriate sampling rate.
+ *
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work. All times here are in uS.
+ */
+#define MIN_SAMPLING_RATE_RATIO (2)
+#define LATENCY_MULTIPLIER (1000)
+#define MIN_LATENCY_MULTIPLIER (100)
+#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
+
+/* Ondemand Sampling types */
+enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
+
+/* Macro creating sysfs show routines */
+#define show_one(_gov, file_name, object) \
+static ssize_t show_##file_name \
+(struct kobject *kobj, struct attribute *attr, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", _gov##_tuners.object); \
+}
+
+#define define_get_cpu_dbs_routines(_dbs_info) \
+static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu) \
+{ \
+ return &per_cpu(_dbs_info, cpu).cdbs; \
+} \
+ \
+static void *get_cpu_dbs_info_s(int cpu) \
+{ \
+ return &per_cpu(_dbs_info, cpu); \
+}
+
+/*
+ * Abbreviations:
+ * dbs: used as a shortform for demand based switching It helps to keep variable
+ * names smaller, simpler
+ * cdbs: common dbs
+ * on_*: On-demand governor
+ * cs_*: Conservative governor
+ */
+
+/* Per cpu structures */
+struct cpu_dbs_common_info {
+ int cpu;
+ u64 prev_cpu_idle;
+ u64 prev_cpu_wall;
+ u64 prev_cpu_nice;
+ struct cpufreq_policy *cur_policy;
+ struct delayed_work work;
+ /*
+ * percpu mutex that serializes governor limit change with gov_dbs_timer
+ * invocation. We do not want gov_dbs_timer to run when user is changing
+ * the governor or limits.
+ */
+ struct mutex timer_mutex;
+};
+
+struct od_cpu_dbs_info_s {
+ struct cpu_dbs_common_info cdbs;
+ u64 prev_cpu_iowait;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int freq_lo;
+ unsigned int freq_lo_jiffies;
+ unsigned int freq_hi_jiffies;
+ unsigned int rate_mult;
+ unsigned int sample_type:1;
+};
+
+struct cs_cpu_dbs_info_s {
+ struct cpu_dbs_common_info cdbs;
+ unsigned int down_skip;
+ unsigned int requested_freq;
+ unsigned int enable:1;
+};
+
+/* Governers sysfs tunables */
+struct od_dbs_tuners {
+ unsigned int ignore_nice;
+ unsigned int sampling_rate;
+ unsigned int sampling_down_factor;
+ unsigned int up_threshold;
+ unsigned int down_differential;
+ unsigned int powersave_bias;
+ unsigned int io_is_busy;
+};
+
+struct cs_dbs_tuners {
+ unsigned int ignore_nice;
+ unsigned int sampling_rate;
+ unsigned int sampling_down_factor;
+ unsigned int up_threshold;
+ unsigned int down_threshold;
+ unsigned int freq_step;
+};
+
+/* Per Governer data */
+struct dbs_data {
+ /* Common across governors */
+ #define GOV_ONDEMAND 0
+ #define GOV_CONSERVATIVE 1
+ int governor;
+ unsigned int min_sampling_rate;
+ unsigned int enable; /* number of CPUs using this policy */
+ struct attribute_group *attr_group;
+ void *tuners;
+
+ /* dbs_mutex protects dbs_enable in governor start/stop */
+ struct mutex mutex;
+
+ struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
+ void *(*get_cpu_dbs_info_s)(int cpu);
+ void (*gov_dbs_timer)(struct work_struct *work);
+ void (*gov_check_cpu)(int cpu, unsigned int load);
+
+ /* Governor specific ops, see below */
+ void *gov_ops;
+};
+
+/* Governor specific ops, will be passed to dbs_data->gov_ops */
+struct od_ops {
+ int (*io_busy)(void);
+ void (*powersave_bias_init_cpu)(int cpu);
+ unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
+ unsigned int freq_next, unsigned int relation);
+ void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+};
+
+struct cs_ops {
+ struct notifier_block *notifier_block;
+};
+
+static inline int delay_for_sampling_rate(unsigned int sampling_rate)
+{
+ int delay = usecs_to_jiffies(sampling_rate);
+
+ /* We want all CPUs to do sampling nearly on same jiffy */
+ if (num_online_cpus() > 1)
+ delay -= jiffies % delay;
+
+ return delay;
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+ struct cpufreq_policy *policy, unsigned int event);
+#endif /* _CPUFREQ_GOVERNER_H */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 396322f2a83f..7731f7c7e79a 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -10,24 +10,23 @@
* published by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/hrtimer.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
#include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/types.h>
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
+/* On-demand governor macors */
#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10)
#define DEF_FREQUENCY_UP_THRESHOLD (80)
#define DEF_SAMPLING_DOWN_FACTOR (1)
@@ -38,80 +37,14 @@
#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO (2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER (1000)
-#define MIN_LATENCY_MULTIPLIER (100)
-#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
- unsigned int event);
+static struct dbs_data od_dbs_data;
+static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static
+static struct cpufreq_governor cpufreq_gov_ondemand;
#endif
-struct cpufreq_governor cpufreq_gov_ondemand = {
- .name = "ondemand",
- .governor = cpufreq_governor_dbs,
- .max_transition_latency = TRANSITION_LATENCY_LIMIT,
- .owner = THIS_MODULE,
-};
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-struct cpu_dbs_info_s {
- cputime64_t prev_cpu_idle;
- cputime64_t prev_cpu_iowait;
- cputime64_t prev_cpu_wall;
- cputime64_t prev_cpu_nice;
- struct cpufreq_policy *cur_policy;
- struct delayed_work work;
- struct cpufreq_frequency_table *freq_table;
- unsigned int freq_lo;
- unsigned int freq_lo_jiffies;
- unsigned int freq_hi_jiffies;
- unsigned int rate_mult;
- int cpu;
- unsigned int sample_type:1;
- /*
- * percpu mutex that serializes governor limit change with
- * do_dbs_timer invocation. We do not want do_dbs_timer to run
- * when user is changing the governor or limits.
- */
- struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
-
-static unsigned int dbs_enable; /* number of CPUs using this policy */
-
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
- unsigned int sampling_rate;
- unsigned int up_threshold;
- unsigned int down_differential;
- unsigned int ignore_nice;
- unsigned int sampling_down_factor;
- unsigned int powersave_bias;
- unsigned int io_is_busy;
-} dbs_tuners_ins = {
+static struct od_dbs_tuners od_tuners = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
@@ -119,48 +52,35 @@ static struct dbs_tuners {
.powersave_bias = 0,
};
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
-{
- u64 idle_time;
- u64 cur_wall_time;
- u64 busy_time;
-
- cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
-
- busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
- busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
-
- idle_time = cur_wall_time - busy_time;
- if (wall)
- *wall = jiffies_to_usecs(cur_wall_time);
-
- return jiffies_to_usecs(idle_time);
-}
-
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void ondemand_powersave_bias_init_cpu(int cpu)
{
- u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
-
- if (idle_time == -1ULL)
- return get_cpu_idle_time_jiffy(cpu, wall);
- else
- idle_time += get_cpu_iowait_time_us(cpu, wall);
+ struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
- return idle_time;
+ dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+ dbs_info->freq_lo = 0;
}
-static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall)
+/*
+ * Not all CPUs want IO time to be accounted as busy; this depends on how
+ * efficient idling at a higher frequency/voltage is.
+ * Pavel Machek says this is not so for various generations of AMD and old
+ * Intel systems.
+ * Mike Chan (androidlcom) calis this is also not true for ARM.
+ * Because of this, whitelist specific known (series) of CPUs by default, and
+ * leave all others up to the user.
+ */
+static int should_io_be_busy(void)
{
- u64 iowait_time = get_cpu_iowait_time_us(cpu, wall);
-
- if (iowait_time == -1ULL)
- return 0;
-
- return iowait_time;
+#if defined(CONFIG_X86)
+ /*
+ * For Intel, Core 2 (model 15) andl later have an efficient idle.
+ */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+ boot_cpu_data.x86 == 6 &&
+ boot_cpu_data.x86_model >= 15)
+ return 1;
+#endif
+ return 0;
}
/*
@@ -169,14 +89,13 @@ static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wal
* freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
*/
static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
- unsigned int freq_next,
- unsigned int relation)
+ unsigned int freq_next, unsigned int relation)
{
unsigned int freq_req, freq_reduc, freq_avg;
unsigned int freq_hi, freq_lo;
unsigned int index = 0;
unsigned int jiffies_total, jiffies_hi, jiffies_lo;
- struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+ struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
policy->cpu);
if (!dbs_info->freq_table) {
@@ -188,7 +107,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
relation, &index);
freq_req = dbs_info->freq_table[index].frequency;
- freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000;
+ freq_reduc = freq_req * od_tuners.powersave_bias / 1000;
freq_avg = freq_req - freq_reduc;
/* Find freq bounds for freq_avg in freq_table */
@@ -207,7 +126,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
dbs_info->freq_lo_jiffies = 0;
return freq_lo;
}
- jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+ jiffies_total = usecs_to_jiffies(od_tuners.sampling_rate);
jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
jiffies_hi += ((freq_hi - freq_lo) / 2);
jiffies_hi /= (freq_hi - freq_lo);
@@ -218,13 +137,6 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
return freq_hi;
}
-static void ondemand_powersave_bias_init_cpu(int cpu)
-{
- struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
- dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
- dbs_info->freq_lo = 0;
-}
-
static void ondemand_powersave_bias_init(void)
{
int i;
@@ -233,83 +145,173 @@ static void ondemand_powersave_bias_init(void)
}
}
-/************************** sysfs interface ************************/
+static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
+{
+ if (od_tuners.powersave_bias)
+ freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
+ else if (p->cur == p->max)
+ return;
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
- struct attribute *attr, char *buf)
+ __cpufreq_driver_target(p, freq, od_tuners.powersave_bias ?
+ CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
+}
+
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate, we look for
+ * a the lowest frequency which can sustain the load while keeping idle time
+ * over 30%. If such a frequency exist, we try to decrease to this frequency.
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of current frequency
+ */
+static void od_check_cpu(int cpu, unsigned int load_freq)
{
- return sprintf(buf, "%u\n", min_sampling_rate);
+ struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+ struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+
+ dbs_info->freq_lo = 0;
+
+ /* Check for frequency increase */
+ if (load_freq > od_tuners.up_threshold * policy->cur) {
+ /* If switching to max speed, apply sampling_down_factor */
+ if (policy->cur < policy->max)
+ dbs_info->rate_mult =
+ od_tuners.sampling_down_factor;
+ dbs_freq_increase(policy, policy->max);
+ return;
+ }
+
+ /* Check for frequency decrease */
+ /* if we cannot reduce the frequency anymore, break out early */
+ if (policy->cur == policy->min)
+ return;
+
+ /*
+ * The optimal frequency is the frequency that is the lowest that can
+ * support the current CPU usage without triggering the up policy. To be
+ * safe, we focus 10 points under the threshold.
+ */
+ if (load_freq < (od_tuners.up_threshold - od_tuners.down_differential) *
+ policy->cur) {
+ unsigned int freq_next;
+ freq_next = load_freq / (od_tuners.up_threshold -
+ od_tuners.down_differential);
+
+ /* No longer fully busy, reset rate_mult */
+ dbs_info->rate_mult = 1;
+
+ if (freq_next < policy->min)
+ freq_next = policy->min;
+
+ if (!od_tuners.powersave_bias) {
+ __cpufreq_driver_target(policy, freq_next,
+ CPUFREQ_RELATION_L);
+ } else {
+ int freq = powersave_bias_target(policy, freq_next,
+ CPUFREQ_RELATION_L);
+ __cpufreq_driver_target(policy, freq,
+ CPUFREQ_RELATION_L);
+ }
+ }
}
-define_one_global_ro(sampling_rate_min);
+static void od_dbs_timer(struct work_struct *work)
+{
+ struct od_cpu_dbs_info_s *dbs_info =
+ container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
+ unsigned int cpu = dbs_info->cdbs.cpu;
+ int delay, sample_type = dbs_info->sample_type;
+
+ mutex_lock(&dbs_info->cdbs.timer_mutex);
+
+ /* Common NORMAL_SAMPLE setup */
+ dbs_info->sample_type = OD_NORMAL_SAMPLE;
+ if (sample_type == OD_SUB_SAMPLE) {
+ delay = dbs_info->freq_lo_jiffies;
+ __cpufreq_driver_target(dbs_info->cdbs.cur_policy,
+ dbs_info->freq_lo, CPUFREQ_RELATION_H);
+ } else {
+ dbs_check_cpu(&od_dbs_data, cpu);
+ if (dbs_info->freq_lo) {
+ /* Setup timer for SUB_SAMPLE */
+ dbs_info->sample_type = OD_SUB_SAMPLE;
+ delay = dbs_info->freq_hi_jiffies;
+ } else {
+ delay = delay_for_sampling_rate(od_tuners.sampling_rate
+ * dbs_info->rate_mult);
+ }
+ }
+
+ schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+ mutex_unlock(&dbs_info->cdbs.timer_mutex);
+}
+
+/************************** sysfs interface ************************/
-/* cpufreq_ondemand Governor Tunables */
-#define show_one(file_name, object) \
-static ssize_t show_##file_name \
-(struct kobject *kobj, struct attribute *attr, char *buf) \
-{ \
- return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
+static ssize_t show_sampling_rate_min(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", od_dbs_data.min_sampling_rate);
}
-show_one(sampling_rate, sampling_rate);
-show_one(io_is_busy, io_is_busy);
-show_one(up_threshold, up_threshold);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(ignore_nice_load, ignore_nice);
-show_one(powersave_bias, powersave_bias);
/**
* update_sampling_rate - update sampling rate effective immediately if needed.
* @new_rate: new sampling rate
*
* If new rate is smaller than the old, simply updaing
- * dbs_tuners_int.sampling_rate might not be appropriate. For example,
- * if the original sampling_rate was 1 second and the requested new sampling
- * rate is 10 ms because the user needs immediate reaction from ondemand
- * governor, but not sure if higher frequency will be required or not,
- * then, the governor may change the sampling rate too late; up to 1 second
- * later. Thus, if we are reducing the sampling rate, we need to make the
- * new value effective immediately.
+ * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the
+ * original sampling_rate was 1 second and the requested new sampling rate is 10
+ * ms because the user needs immediate reaction from ondemand governor, but not
+ * sure if higher frequency will be required or not, then, the governor may
+ * change the sampling rate too late; up to 1 second later. Thus, if we are
+ * reducing the sampling rate, we need to make the new value effective
+ * immediately.
*/
static void update_sampling_rate(unsigned int new_rate)
{
int cpu;
- dbs_tuners_ins.sampling_rate = new_rate
- = max(new_rate, min_sampling_rate);
+ od_tuners.sampling_rate = new_rate = max(new_rate,
+ od_dbs_data.min_sampling_rate);
for_each_online_cpu(cpu) {
struct cpufreq_policy *policy;
- struct cpu_dbs_info_s *dbs_info;
+ struct od_cpu_dbs_info_s *dbs_info;
unsigned long next_sampling, appointed_at;
policy = cpufreq_cpu_get(cpu);
if (!policy)
continue;
+ if (policy->governor != &cpufreq_gov_ondemand) {
+ cpufreq_cpu_put(policy);
+ continue;
+ }
dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
cpufreq_cpu_put(policy);
- mutex_lock(&dbs_info->timer_mutex);
+ mutex_lock(&dbs_info->cdbs.timer_mutex);
- if (!delayed_work_pending(&dbs_info->work)) {
- mutex_unlock(&dbs_info->timer_mutex);
+ if (!delayed_work_pending(&dbs_info->cdbs.work)) {
+ mutex_unlock(&dbs_info->cdbs.timer_mutex);
continue;
}
- next_sampling = jiffies + usecs_to_jiffies(new_rate);
- appointed_at = dbs_info->work.timer.expires;
-
+ next_sampling = jiffies + usecs_to_jiffies(new_rate);
+ appointed_at = dbs_info->cdbs.work.timer.expires;
if (time_before(next_sampling, appointed_at)) {
- mutex_unlock(&dbs_info->timer_mutex);
- cancel_delayed_work_sync(&dbs_info->work);
- mutex_lock(&dbs_info->timer_mutex);
+ mutex_unlock(&dbs_info->cdbs.timer_mutex);
+ cancel_delayed_work_sync(&dbs_info->cdbs.work);
+ mutex_lock(&dbs_info->cdbs.timer_mutex);
- schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
- usecs_to_jiffies(new_rate));
+ schedule_delayed_work_on(dbs_info->cdbs.cpu,
+ &dbs_info->cdbs.work,
+ usecs_to_jiffies(new_rate));
}
- mutex_unlock(&dbs_info->timer_mutex);
+ mutex_unlock(&dbs_info->cdbs.timer_mutex);
}
}
@@ -334,7 +336,7 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
ret = sscanf(buf, "%u", &input);
if (ret != 1)
return -EINVAL;
- dbs_tuners_ins.io_is_busy = !!input;
+ od_tuners.io_is_busy = !!input;
return count;
}
@@ -349,7 +351,7 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
input < MIN_FREQUENCY_UP_THRESHOLD) {
return -EINVAL;
}
- dbs_tuners_ins.up_threshold = input;
+ od_tuners.up_threshold = input;
return count;
}
@@ -362,12 +364,12 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
return -EINVAL;
- dbs_tuners_ins.sampling_down_factor = input;
+ od_tuners.sampling_down_factor = input;
/* Reset down sampling multiplier in case it was active */
for_each_online_cpu(j) {
- struct cpu_dbs_info_s *dbs_info;
- dbs_info = &per_cpu(od_cpu_dbs_info, j);
+ struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+ j);
dbs_info->rate_mult = 1;
}
return count;
@@ -388,19 +390,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
if (input > 1)
input = 1;
- if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
+ if (input == od_tuners.ignore_nice) { /* nothing to do */
return count;
}
- dbs_tuners_ins.ignore_nice = input;
+ od_tuners.ignore_nice = input;
/* we need to re-evaluate prev_cpu_idle */
for_each_online_cpu(j) {
- struct cpu_dbs_info_s *dbs_info;
+ struct od_cpu_dbs_info_s *dbs_info;
dbs_info = &per_cpu(od_cpu_dbs_info, j);
- dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
- &dbs_info->prev_cpu_wall);
- if (dbs_tuners_ins.ignore_nice)
- dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+ dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+ &dbs_info->cdbs.prev_cpu_wall);
+ if (od_tuners.ignore_nice)
+ dbs_info->cdbs.prev_cpu_nice =
+ kcpustat_cpu(j).cpustat[CPUTIME_NICE];
}
return count;
@@ -419,17 +422,25 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
if (input > 1000)
input = 1000;
- dbs_tuners_ins.powersave_bias = input;
+ od_tuners.powersave_bias = input;
ondemand_powersave_bias_init();
return count;
}
+show_one(od, sampling_rate, sampling_rate);
+show_one(od, io_is_busy, io_is_busy);
+show_one(od, up_threshold, up_threshold);
+show_one(od, sampling_down_factor, sampling_down_factor);
+show_one(od, ignore_nice_load, ignore_nice);
+show_one(od, powersave_bias, powersave_bias);
+
define_one_global_rw(sampling_rate);
define_one_global_rw(io_is_busy);
define_one_global_rw(up_threshold);
define_one_global_rw(sampling_down_factor);
define_one_global_rw(ignore_nice_load);
define_one_global_rw(powersave_bias);
+define_one_global_ro(sampling_rate_min);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -442,354 +453,71 @@ static struct attribute *dbs_attributes[] = {
NULL
};
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group od_attr_group = {
.attrs = dbs_attributes,
.name = "ondemand",
};
/************************** sysfs end ************************/
-static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
-{
- if (dbs_tuners_ins.powersave_bias)
- freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
- else if (p->cur == p->max)
- return;
-
- __cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ?
- CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
-}
-
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
- unsigned int max_load_freq;
-
- struct cpufreq_policy *policy;
- unsigned int j;
-
- this_dbs_info->freq_lo = 0;
- policy = this_dbs_info->cur_policy;
-
- /*
- * Every sampling_rate, we check, if current idle time is less
- * than 20% (default), then we try to increase frequency
- * Every sampling_rate, we look for a the lowest
- * frequency which can sustain the load while keeping idle time over
- * 30%. If such a frequency exist, we try to decrease to this frequency.
- *
- * Any frequency increase takes it to the maximum frequency.
- * Frequency reduction happens at minimum steps of
- * 5% (default) of current frequency
- */
-
- /* Get Absolute Load - in terms of freq */
- max_load_freq = 0;
-
- for_each_cpu(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
- cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
- unsigned int idle_time, wall_time, iowait_time;
- unsigned int load, load_freq;
- int freq_avg;
-
- j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-
- cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
- cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time);
-
- wall_time = (unsigned int)
- (cur_wall_time - j_dbs_info->prev_cpu_wall);
- j_dbs_info->prev_cpu_wall = cur_wall_time;
-
- idle_time = (unsigned int)
- (cur_idle_time - j_dbs_info->prev_cpu_idle);
- j_dbs_info->prev_cpu_idle = cur_idle_time;
-
- iowait_time = (unsigned int)
- (cur_iowait_time - j_dbs_info->prev_cpu_iowait);
- j_dbs_info->prev_cpu_iowait = cur_iowait_time;
-
- if (dbs_tuners_ins.ignore_nice) {
- u64 cur_nice;
- unsigned long cur_nice_jiffies;
-
- cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
- j_dbs_info->prev_cpu_nice;
- /*
- * Assumption: nice time between sampling periods will
- * be less than 2^32 jiffies for 32 bit sys
- */
- cur_nice_jiffies = (unsigned long)
- cputime64_to_jiffies64(cur_nice);
-
- j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
- idle_time += jiffies_to_usecs(cur_nice_jiffies);
- }
-
- /*
- * For the purpose of ondemand, waiting for disk IO is an
- * indication that you're performance critical, and not that
- * the system is actually idle. So subtract the iowait time
- * from the cpu idle time.
- */
-
- if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time)
- idle_time -= iowait_time;
-
- if (unlikely(!wall_time || wall_time < idle_time))
- continue;
-
- load = 100 * (wall_time - idle_time) / wall_time;
-
- freq_avg = __cpufreq_driver_getavg(policy, j);
- if (freq_avg <= 0)
- freq_avg = policy->cur;
-
- load_freq = load * freq_avg;
- if (load_freq > max_load_freq)
- max_load_freq = load_freq;
- }
+define_get_cpu_dbs_routines(od_cpu_dbs_info);
- /* Check for frequency increase */
- if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
- /* If switching to max speed, apply sampling_down_factor */
- if (policy->cur < policy->max)
- this_dbs_info->rate_mult =
- dbs_tuners_ins.sampling_down_factor;
- dbs_freq_increase(policy, policy->max);
- return;
- }
-
- /* Check for frequency decrease */
- /* if we cannot reduce the frequency anymore, break out early */
- if (policy->cur == policy->min)
- return;
-
- /*
- * The optimal frequency is the frequency that is the lowest that
- * can support the current CPU usage without triggering the up
- * policy. To be safe, we focus 10 points under the threshold.
- */
- if (max_load_freq <
- (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
- policy->cur) {
- unsigned int freq_next;
- freq_next = max_load_freq /
- (dbs_tuners_ins.up_threshold -
- dbs_tuners_ins.down_differential);
-
- /* No longer fully busy, reset rate_mult */
- this_dbs_info->rate_mult = 1;
-
- if (freq_next < policy->min)
- freq_next = policy->min;
-
- if (!dbs_tuners_ins.powersave_bias) {
- __cpufreq_driver_target(policy, freq_next,
- CPUFREQ_RELATION_L);
- } else {
- int freq = powersave_bias_target(policy, freq_next,
- CPUFREQ_RELATION_L);
- __cpufreq_driver_target(policy, freq,
- CPUFREQ_RELATION_L);
- }
- }
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
- struct cpu_dbs_info_s *dbs_info =
- container_of(work, struct cpu_dbs_info_s, work.work);
- unsigned int cpu = dbs_info->cpu;
- int sample_type = dbs_info->sample_type;
-
- int delay;
-
- mutex_lock(&dbs_info->timer_mutex);
-
- /* Common NORMAL_SAMPLE setup */
- dbs_info->sample_type = DBS_NORMAL_SAMPLE;
- if (!dbs_tuners_ins.powersave_bias ||
- sample_type == DBS_NORMAL_SAMPLE) {
- dbs_check_cpu(dbs_info);
- if (dbs_info->freq_lo) {
- /* Setup timer for SUB_SAMPLE */
- dbs_info->sample_type = DBS_SUB_SAMPLE;
- delay = dbs_info->freq_hi_jiffies;
- } else {
- /* We want all CPUs to do sampling nearly on
- * same jiffy
- */
- delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
- * dbs_info->rate_mult);
-
- if (num_online_cpus() > 1)
- delay -= jiffies % delay;
- }
- } else {
- __cpufreq_driver_target(dbs_info->cur_policy,
- dbs_info->freq_lo, CPUFREQ_RELATION_H);
- delay = dbs_info->freq_lo_jiffies;
- }
- schedule_delayed_work_on(cpu, &dbs_info->work, delay);
- mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
- /* We want all CPUs to do sampling nearly on same jiffy */
- int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
- if (num_online_cpus() > 1)
- delay -= jiffies % delay;
+static struct od_ops od_ops = {
+ .io_busy = should_io_be_busy,
+ .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
+ .powersave_bias_target = powersave_bias_target,
+ .freq_increase = dbs_freq_increase,
+};
- dbs_info->sample_type = DBS_NORMAL_SAMPLE;
- INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
- schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct dbs_data od_dbs_data = {
+ .governor = GOV_ONDEMAND,
+ .attr_group = &od_attr_group,
+ .tuners = &od_tuners,
+ .get_cpu_cdbs = get_cpu_cdbs,
+ .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+ .gov_dbs_timer = od_dbs_timer,
+ .gov_check_cpu = od_check_cpu,
+ .gov_ops = &od_ops,
+};
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
+static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
+ unsigned int event)
{
- cancel_delayed_work_sync(&dbs_info->work);
+ return cpufreq_governor_dbs(&od_dbs_data, policy, event);
}
-/*
- * Not all CPUs want IO time to be accounted as busy; this dependson how
- * efficient idling at a higher frequency/voltage is.
- * Pavel Machek says this is not so for various generations of AMD and old
- * Intel systems.
- * Mike Chan (androidlcom) calis this is also not true for ARM.
- * Because of this, whitelist specific known (series) of CPUs by default, and
- * leave all others up to the user.
- */
-static int should_io_be_busy(void)
-{
-#if defined(CONFIG_X86)
- /*
- * For Intel, Core 2 (model 15) andl later have an efficient idle.
- */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
- boot_cpu_data.x86 == 6 &&
- boot_cpu_data.x86_model >= 15)
- return 1;
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
#endif
- return 0;
-}
-
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
- unsigned int event)
-{
- unsigned int cpu = policy->cpu;
- struct cpu_dbs_info_s *this_dbs_info;
- unsigned int j;
- int rc;
-
- this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-
- switch (event) {
- case CPUFREQ_GOV_START:
- if ((!cpu_online(cpu)) || (!policy->cur))
- return -EINVAL;
-
- mutex_lock(&dbs_mutex);
-
- dbs_enable++;
- for_each_cpu(j, policy->cpus) {
- struct cpu_dbs_info_s *j_dbs_info;
- j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
- j_dbs_info->cur_policy = policy;
-
- j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
- &j_dbs_info->prev_cpu_wall);
- if (dbs_tuners_ins.ignore_nice)
- j_dbs_info->prev_cpu_nice =
- kcpustat_cpu(j).cpustat[CPUTIME_NICE];
- }
- this_dbs_info->cpu = cpu;
- this_dbs_info->rate_mult = 1;
- ondemand_powersave_bias_init_cpu(cpu);
- /*
- * Start the timerschedule work, when this governor
- * is used for first time
- */
- if (dbs_enable == 1) {
- unsigned int latency;
-
- rc = sysfs_create_group(cpufreq_global_kobject,
- &dbs_attr_group);
- if (rc) {
- mutex_unlock(&dbs_mutex);
- return rc;
- }
-
- /* policy latency is in nS. Convert it to uS first */
- latency = policy->cpuinfo.transition_latency / 1000;
- if (latency == 0)
- latency = 1;
- /* Bring kernel and HW constraints together */
- min_sampling_rate = max(min_sampling_rate,
- MIN_LATENCY_MULTIPLIER * latency);
- dbs_tuners_ins.sampling_rate =
- max(min_sampling_rate,
- latency * LATENCY_MULTIPLIER);
- dbs_tuners_ins.io_is_busy = should_io_be_busy();
- }
- mutex_unlock(&dbs_mutex);
-
- mutex_init(&this_dbs_info->timer_mutex);
- dbs_timer_init(this_dbs_info);
- break;
-
- case CPUFREQ_GOV_STOP:
- dbs_timer_exit(this_dbs_info);
-
- mutex_lock(&dbs_mutex);
- mutex_destroy(&this_dbs_info->timer_mutex);
- dbs_enable--;
- mutex_unlock(&dbs_mutex);
- if (!dbs_enable)
- sysfs_remove_group(cpufreq_global_kobject,
- &dbs_attr_group);
-
- break;
-
- case CPUFREQ_GOV_LIMITS:
- mutex_lock(&this_dbs_info->timer_mutex);
- if (policy->max < this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(this_dbs_info->cur_policy,
- policy->max, CPUFREQ_RELATION_H);
- else if (policy->min > this_dbs_info->cur_policy->cur)
- __cpufreq_driver_target(this_dbs_info->cur_policy,
- policy->min, CPUFREQ_RELATION_L);
- dbs_check_cpu(this_dbs_info);
- mutex_unlock(&this_dbs_info->timer_mutex);
- break;
- }
- return 0;
-}
+struct cpufreq_governor cpufreq_gov_ondemand = {
+ .name = "ondemand",
+ .governor = od_cpufreq_governor_dbs,
+ .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+ .owner = THIS_MODULE,
+};
static int __init cpufreq_gov_dbs_init(void)
{
u64 idle_time;
int cpu = get_cpu();
+ mutex_init(&od_dbs_data.mutex);
idle_time = get_cpu_idle_time_us(cpu, NULL);
put_cpu();
if (idle_time != -1ULL) {
/* Idle micro accounting is supported. Use finer thresholds */
- dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
- dbs_tuners_ins.down_differential =
- MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+ od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+ od_tuners.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
/*
* In nohz/micro accounting case we set the minimum frequency
* not depending on HZ, but fixed (very low). The deferred
* timer might skip some samples if idle/sleeping as needed.
*/
- min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+ od_dbs_data.min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
} else {
/* For correct statistics, we need 10 ticks for each measure */
- min_sampling_rate =
- MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
+ od_dbs_data.min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+ jiffies_to_usecs(10);
}
return cpufreq_register_governor(&cpufreq_gov_ondemand);
@@ -800,7 +528,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
cpufreq_unregister_governor(&cpufreq_gov_ondemand);
}
-
MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index f13a8a9af6a1..ceee06849b91 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -10,6 +10,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufreq.h>
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 4c2eb512f2bc..2d948a171155 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -10,6 +10,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufreq.h>
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 399831690fed..e40e50809644 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -37,7 +37,7 @@ struct cpufreq_stats {
unsigned int max_state;
unsigned int state_num;
unsigned int last_index;
- cputime64_t *time_in_state;
+ u64 *time_in_state;
unsigned int *freq_table;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
unsigned int *trans_table;
@@ -223,7 +223,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
count++;
}
- alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
+ alloc_size = count * sizeof(int) + count * sizeof(u64);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size += count * count * sizeof(int);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index bedac1aa9be3..c8c3d293cc57 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -11,6 +11,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/smp.h>
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 74b830b635a6..4f154bc0ebe4 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -8,43 +8,17 @@
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <mach/id.h>
-static struct cpufreq_frequency_table freq_table[] = {
- [0] = {
- .index = 0,
- .frequency = 200000,
- },
- [1] = {
- .index = 1,
- .frequency = 400000,
- },
- [2] = {
- .index = 2,
- .frequency = 800000,
- },
- [3] = {
- /* Used for MAX_OPP, if available */
- .index = 3,
- .frequency = CPUFREQ_TABLE_END,
- },
- [4] = {
- .index = 4,
- .frequency = CPUFREQ_TABLE_END,
- },
-};
-
-static enum arm_opp idx2opp[] = {
- ARM_EXTCLK,
- ARM_50_OPP,
- ARM_100_OPP,
- ARM_MAX_OPP
-};
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *armss_clk;
static struct freq_attr *db8500_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
@@ -85,9 +59,9 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
for_each_cpu(freqs.cpu, policy->cpus)
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- /* request the PRCM unit for opp change */
- if (prcmu_set_arm_opp(idx2opp[idx])) {
- pr_err("db8500-cpufreq: Failed to set OPP level\n");
+ /* update armss clk frequency */
+ if (clk_set_rate(armss_clk, freq_table[idx].frequency * 1000)) {
+ pr_err("db8500-cpufreq: Failed to update armss clk\n");
return -EINVAL;
}
@@ -100,25 +74,36 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
{
- int i;
- /* request the prcm to get the current ARM opp */
- for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
- ;
- return freq_table[i].frequency;
+ int i = 0;
+ unsigned long freq = clk_get_rate(armss_clk) / 1000;
+
+ while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
+ if (freq <= freq_table[i].frequency)
+ return freq_table[i].frequency;
+ i++;
+ }
+
+ /* We could not find a corresponding frequency. */
+ pr_err("db8500-cpufreq: Failed to find cpufreq speed\n");
+ return 0;
}
static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
{
- int i, res;
-
- BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
+ int i = 0;
+ int res;
- if (prcmu_has_arm_maxopp())
- freq_table[3].frequency = 1000000;
+ armss_clk = clk_get(NULL, "armss");
+ if (IS_ERR(armss_clk)) {
+ pr_err("db8500-cpufreq : Failed to get armss clk\n");
+ return PTR_ERR(armss_clk);
+ }
pr_info("db8500-cpufreq : Available frequencies:\n");
- for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+ while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
pr_info(" %d Mhz\n", freq_table[i].frequency/1000);
+ i++;
+ }
/* get policy fields based on the table */
res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -126,6 +111,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
else {
pr_err("db8500-cpufreq : Failed to read policy table\n");
+ clk_put(armss_clk);
return res;
}
@@ -159,12 +145,35 @@ static struct cpufreq_driver db8500_cpufreq_driver = {
.attr = db8500_cpufreq_attr,
};
+static int db8500_cpufreq_probe(struct platform_device *pdev)
+{
+ freq_table = dev_get_platdata(&pdev->dev);
+
+ if (!freq_table) {
+ pr_err("db8500-cpufreq: Failed to fetch cpufreq table\n");
+ return -ENODEV;
+ }
+
+ return cpufreq_register_driver(&db8500_cpufreq_driver);
+}
+
+static struct platform_driver db8500_cpufreq_plat_driver = {
+ .driver = {
+ .name = "cpufreq-u8500",
+ .owner = THIS_MODULE,
+ },
+ .probe = db8500_cpufreq_probe,
+};
+
static int __init db8500_cpufreq_register(void)
{
if (!cpu_is_u8500_family())
return -ENODEV;
pr_info("cpufreq for DB8500 started\n");
- return cpufreq_register_driver(&db8500_cpufreq_driver);
+ return platform_driver_register(&db8500_cpufreq_plat_driver);
}
device_initcall(db8500_cpufreq_register);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("cpufreq driver for DB8500");
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index af2d81e10f71..7012ea8bf1e7 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -31,13 +31,13 @@ static unsigned int locking_frequency;
static bool frequency_locked;
static DEFINE_MUTEX(cpufreq_lock);
-int exynos_verify_speed(struct cpufreq_policy *policy)
+static int exynos_verify_speed(struct cpufreq_policy *policy)
{
return cpufreq_frequency_table_verify(policy,
exynos_info->freq_table);
}
-unsigned int exynos_getspeed(unsigned int cpu)
+static unsigned int exynos_getspeed(unsigned int cpu)
{
return clk_get_rate(exynos_info->cpu_clk) / 1000;
}
@@ -100,7 +100,8 @@ static int exynos_target(struct cpufreq_policy *policy,
}
arm_volt = volt_table[index];
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ for_each_cpu(freqs.cpu, policy->cpus)
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/* When the new frequency is higher than current frequency */
if ((freqs.new > freqs.old) && !safe_arm_volt) {
@@ -115,7 +116,8 @@ static int exynos_target(struct cpufreq_policy *policy,
if (freqs.new != freqs.old)
exynos_info->set_freq(old_index, index);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ for_each_cpu(freqs.cpu, policy->cpus)
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
/* When the new frequency is lower than current frequency */
if ((freqs.new < freqs.old) ||
@@ -235,6 +237,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_copy(policy->related_cpus, cpu_possible_mask);
cpumask_copy(policy->cpus, cpu_online_mask);
} else {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
cpumask_setall(policy->cpus);
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 90431cb92804..49cda256efb2 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -9,6 +9,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 53ddbc760af7..f1fa500ac105 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -930,7 +930,7 @@ static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
return 0;
}
-static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
+static int longhaul_cpu_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
@@ -946,7 +946,7 @@ static struct cpufreq_driver longhaul_driver = {
.target = longhaul_target,
.get = longhaul_get,
.init = longhaul_cpu_init,
- .exit = __devexit_p(longhaul_cpu_exit),
+ .exit = longhaul_cpu_exit,
.name = "longhaul",
.owner = THIS_MODULE,
.attr = longhaul_attr,
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index e3ebb4fa2c3e..056faf6af1a9 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1186,7 +1186,7 @@ err_out:
return -ENODEV;
}
-static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
+static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
@@ -1242,7 +1242,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
.target = powernowk8_target,
.bios_limit = acpi_processor_get_bios_limit,
.init = powernowk8_cpu_init,
- .exit = __devexit_p(powernowk8_cpu_exit),
+ .exit = powernowk8_cpu_exit,
.get = powernowk8_get,
.name = "powernow-k8",
.owner = THIS_MODULE,
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
new file mode 100644
index 000000000000..4575cfe41755
--- /dev/null
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -0,0 +1,291 @@
+/*
+ * drivers/cpufreq/spear-cpufreq.c
+ *
+ * CPU Frequency Scaling for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Deepak Sikri <deepak.sikri@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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* SPEAr CPUFreq driver data structure */
+static struct {
+ struct clk *clk;
+ unsigned int transition_latency;
+ struct cpufreq_frequency_table *freq_tbl;
+ u32 cnt;
+} spear_cpufreq;
+
+int spear_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl);
+}
+
+static unsigned int spear_cpufreq_get(unsigned int cpu)
+{
+ return clk_get_rate(spear_cpufreq.clk) / 1000;
+}
+
+static struct clk *spear1340_cpu_get_possible_parent(unsigned long newfreq)
+{
+ struct clk *sys_pclk;
+ int pclk;
+ /*
+ * In SPEAr1340, cpu clk's parent sys clk can take input from
+ * following sources
+ */
+ const char *sys_clk_src[] = {
+ "sys_syn_clk",
+ "pll1_clk",
+ "pll2_clk",
+ "pll3_clk",
+ };
+
+ /*
+ * As sys clk can have multiple source with their own range
+ * limitation so we choose possible sources accordingly
+ */
+ if (newfreq <= 300000000)
+ pclk = 0; /* src is sys_syn_clk */
+ else if (newfreq > 300000000 && newfreq <= 500000000)
+ pclk = 3; /* src is pll3_clk */
+ else if (newfreq == 600000000)
+ pclk = 1; /* src is pll1_clk */
+ else
+ return ERR_PTR(-EINVAL);
+
+ /* Get parent to sys clock */
+ sys_pclk = clk_get(NULL, sys_clk_src[pclk]);
+ if (IS_ERR(sys_pclk))
+ pr_err("Failed to get %s clock\n", sys_clk_src[pclk]);
+
+ return sys_pclk;
+}
+
+/*
+ * In SPEAr1340, we cannot use newfreq directly because we need to actually
+ * access a source clock (clk) which might not be ancestor of cpu at present.
+ * Hence in SPEAr1340 we would operate on source clock directly before switching
+ * cpu clock to it.
+ */
+static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
+{
+ struct clk *sys_clk;
+ int ret = 0;
+
+ sys_clk = clk_get_parent(spear_cpufreq.clk);
+ if (IS_ERR(sys_clk)) {
+ pr_err("failed to get cpu's parent (sys) clock\n");
+ return PTR_ERR(sys_clk);
+ }
+
+ /* Set the rate of the source clock before changing the parent */
+ ret = clk_set_rate(sys_pclk, newfreq);
+ if (ret) {
+ pr_err("Failed to set sys clk rate to %lu\n", newfreq);
+ return ret;
+ }
+
+ ret = clk_set_parent(sys_clk, sys_pclk);
+ if (ret) {
+ pr_err("Failed to set sys clk parent\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int spear_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ unsigned long newfreq;
+ struct clk *srcclk;
+ int index, ret, mult = 1;
+
+ if (cpufreq_frequency_table_target(policy, spear_cpufreq.freq_tbl,
+ target_freq, relation, &index))
+ return -EINVAL;
+
+ freqs.cpu = policy->cpu;
+ freqs.old = spear_cpufreq_get(0);
+
+ newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
+ if (of_machine_is_compatible("st,spear1340")) {
+ /*
+ * SPEAr1340 is special in the sense that due to the possibility
+ * of multiple clock sources for cpu clk's parent we can have
+ * different clock source for different frequency of cpu clk.
+ * Hence we need to choose one from amongst these possible clock
+ * sources.
+ */
+ srcclk = spear1340_cpu_get_possible_parent(newfreq);
+ if (IS_ERR(srcclk)) {
+ pr_err("Failed to get src clk\n");
+ return PTR_ERR(srcclk);
+ }
+
+ /* SPEAr1340: src clk is always 2 * intended cpu clk */
+ mult = 2;
+ } else {
+ /*
+ * src clock to be altered is ancestor of cpu clock. Hence we
+ * can directly work on cpu clk
+ */
+ srcclk = spear_cpufreq.clk;
+ }
+
+ newfreq = clk_round_rate(srcclk, newfreq * mult);
+ if (newfreq < 0) {
+ pr_err("clk_round_rate failed for cpu src clock\n");
+ return newfreq;
+ }
+
+ freqs.new = newfreq / 1000;
+ freqs.new /= mult;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ if (mult == 2)
+ ret = spear1340_set_cpu_rate(srcclk, newfreq);
+ else
+ ret = clk_set_rate(spear_cpufreq.clk, newfreq);
+
+ /* Get current rate after clk_set_rate, in case of failure */
+ if (ret) {
+ pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
+ freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
+ }
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ return ret;
+}
+
+static int spear_cpufreq_init(struct cpufreq_policy *policy)
+{
+ int ret;
+
+ ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
+ if (ret) {
+ pr_err("cpufreq_frequency_table_cpuinfo() failed");
+ return ret;
+ }
+
+ cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu);
+ policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency;
+ policy->cur = spear_cpufreq_get(0);
+
+ cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+ cpumask_copy(policy->related_cpus, policy->cpus);
+
+ return 0;
+}
+
+static int spear_cpufreq_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+static struct freq_attr *spear_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver spear_cpufreq_driver = {
+ .name = "cpufreq-spear",
+ .flags = CPUFREQ_STICKY,
+ .verify = spear_cpufreq_verify,
+ .target = spear_cpufreq_target,
+ .get = spear_cpufreq_get,
+ .init = spear_cpufreq_init,
+ .exit = spear_cpufreq_exit,
+ .attr = spear_cpufreq_attr,
+};
+
+static int spear_cpufreq_driver_init(void)
+{
+ struct device_node *np;
+ const struct property *prop;
+ struct cpufreq_frequency_table *freq_tbl;
+ const __be32 *val;
+ int cnt, i, ret;
+
+ np = of_find_node_by_path("/cpus/cpu@0");
+ if (!np) {
+ pr_err("No cpu node found");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(np, "clock-latency",
+ &spear_cpufreq.transition_latency))
+ spear_cpufreq.transition_latency = CPUFREQ_ETERNAL;
+
+ prop = of_find_property(np, "cpufreq_tbl", NULL);
+ if (!prop || !prop->value) {
+ pr_err("Invalid cpufreq_tbl");
+ ret = -ENODEV;
+ goto out_put_node;
+ }
+
+ cnt = prop->length / sizeof(u32);
+ val = prop->value;
+
+ freq_tbl = kmalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
+ if (!freq_tbl) {
+ ret = -ENOMEM;
+ goto out_put_node;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ freq_tbl[i].index = i;
+ freq_tbl[i].frequency = be32_to_cpup(val++);
+ }
+
+ freq_tbl[i].index = i;
+ freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+
+ spear_cpufreq.freq_tbl = freq_tbl;
+
+ of_node_put(np);
+
+ spear_cpufreq.clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(spear_cpufreq.clk)) {
+ pr_err("Unable to get CPU clock\n");
+ ret = PTR_ERR(spear_cpufreq.clk);
+ goto out_put_mem;
+ }
+
+ ret = cpufreq_register_driver(&spear_cpufreq_driver);
+ if (!ret)
+ return 0;
+
+ pr_err("failed register driver: %d\n", ret);
+ clk_put(spear_cpufreq.clk);
+
+out_put_mem:
+ kfree(freq_tbl);
+ return ret;
+
+out_put_node:
+ of_node_put(np);
+ return ret;
+}
+late_initcall(spear_cpufreq_driver_init);
+
+MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
+MODULE_DESCRIPTION("SPEAr CPUFreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index a76b689e553b..234ae651b38f 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -9,6 +9,15 @@ config CPU_IDLE
If you're using an ACPI-enabled platform, you should say Y here.
+config CPU_IDLE_MULTIPLE_DRIVERS
+ bool "Support multiple cpuidle drivers"
+ depends on CPU_IDLE
+ default n
+ help
+ Allows the cpuidle framework to use different drivers for each CPU.
+ This is useful if you have a system with different CPU latencies and
+ states. If unsure say N.
+
config CPU_IDLE_GOV_LADDER
bool
depends on CPU_IDLE
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 7f15b8514a18..8df53dd8dbe1 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -68,7 +68,7 @@ static cpuidle_enter_t cpuidle_enter_ops;
int cpuidle_play_dead(void)
{
struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
- struct cpuidle_driver *drv = cpuidle_get_driver();
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
int i, dead_state = -1;
int power_usage = -1;
@@ -109,8 +109,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
/* This can be moved to within driver enter routine
* but that results in multiple copies of same code.
*/
- dev->states_usage[entered_state].time +=
- (unsigned long long)dev->last_residency;
+ dev->states_usage[entered_state].time += dev->last_residency;
dev->states_usage[entered_state].usage++;
} else {
dev->last_residency = 0;
@@ -128,7 +127,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
int cpuidle_idle_call(void)
{
struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
- struct cpuidle_driver *drv = cpuidle_get_driver();
+ struct cpuidle_driver *drv;
int next_state, entered_state;
if (off)
@@ -141,9 +140,15 @@ int cpuidle_idle_call(void)
if (!dev || !dev->enabled)
return -EBUSY;
+ drv = cpuidle_get_cpu_driver(dev);
+
/* ask the governor for the next state */
next_state = cpuidle_curr_governor->select(drv, dev);
if (need_resched()) {
+ dev->last_residency = 0;
+ /* give the governor an opportunity to reflect on the outcome */
+ if (cpuidle_curr_governor->reflect)
+ cpuidle_curr_governor->reflect(dev, next_state);
local_irq_enable();
return 0;
}
@@ -308,15 +313,19 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
int cpuidle_enable_device(struct cpuidle_device *dev)
{
int ret, i;
- struct cpuidle_driver *drv = cpuidle_get_driver();
+ struct cpuidle_driver *drv;
if (!dev)
return -EINVAL;
if (dev->enabled)
return 0;
+
+ drv = cpuidle_get_cpu_driver(dev);
+
if (!drv || !cpuidle_curr_governor)
return -EIO;
+
if (!dev->state_count)
dev->state_count = drv->state_count;
@@ -331,7 +340,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
poll_idle_init(drv);
- if ((ret = cpuidle_add_state_sysfs(dev)))
+ ret = cpuidle_add_device_sysfs(dev);
+ if (ret)
return ret;
if (cpuidle_curr_governor->enable &&
@@ -352,7 +362,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
return 0;
fail_sysfs:
- cpuidle_remove_state_sysfs(dev);
+ cpuidle_remove_device_sysfs(dev);
return ret;
}
@@ -368,17 +378,20 @@ EXPORT_SYMBOL_GPL(cpuidle_enable_device);
*/
void cpuidle_disable_device(struct cpuidle_device *dev)
{
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
if (!dev || !dev->enabled)
return;
- if (!cpuidle_get_driver() || !cpuidle_curr_governor)
+
+ if (!drv || !cpuidle_curr_governor)
return;
dev->enabled = 0;
if (cpuidle_curr_governor->disable)
- cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
+ cpuidle_curr_governor->disable(drv, dev);
- cpuidle_remove_state_sysfs(dev);
+ cpuidle_remove_device_sysfs(dev);
enabled_devices--;
}
@@ -394,17 +407,14 @@ EXPORT_SYMBOL_GPL(cpuidle_disable_device);
static int __cpuidle_register_device(struct cpuidle_device *dev)
{
int ret;
- struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
- struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
- if (!try_module_get(cpuidle_driver->owner))
+ if (!try_module_get(drv->owner))
return -EINVAL;
- init_completion(&dev->kobj_unregister);
-
per_cpu(cpuidle_devices, dev->cpu) = dev;
list_add(&dev->device_list, &cpuidle_detected_devices);
- ret = cpuidle_add_sysfs(cpu_dev);
+ ret = cpuidle_add_sysfs(dev);
if (ret)
goto err_sysfs;
@@ -416,12 +426,11 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
return 0;
err_coupled:
- cpuidle_remove_sysfs(cpu_dev);
- wait_for_completion(&dev->kobj_unregister);
+ cpuidle_remove_sysfs(dev);
err_sysfs:
list_del(&dev->device_list);
per_cpu(cpuidle_devices, dev->cpu) = NULL;
- module_put(cpuidle_driver->owner);
+ module_put(drv->owner);
return ret;
}
@@ -460,8 +469,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
*/
void cpuidle_unregister_device(struct cpuidle_device *dev)
{
- struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
- struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
if (dev->registered == 0)
return;
@@ -470,16 +478,15 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
cpuidle_disable_device(dev);
- cpuidle_remove_sysfs(cpu_dev);
+ cpuidle_remove_sysfs(dev);
list_del(&dev->device_list);
- wait_for_completion(&dev->kobj_unregister);
per_cpu(cpuidle_devices, dev->cpu) = NULL;
cpuidle_coupled_unregister_device(dev);
cpuidle_resume_and_unlock();
- module_put(cpuidle_driver->owner);
+ module_put(drv->owner);
}
EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h
index 76e7f696ad8c..ee97e9672ecf 100644
--- a/drivers/cpuidle/cpuidle.h
+++ b/drivers/cpuidle/cpuidle.h
@@ -5,8 +5,6 @@
#ifndef __DRIVER_CPUIDLE_H
#define __DRIVER_CPUIDLE_H
-#include <linux/device.h>
-
/* For internal use only */
extern struct cpuidle_governor *cpuidle_curr_governor;
extern struct list_head cpuidle_governors;
@@ -25,12 +23,15 @@ extern void cpuidle_uninstall_idle_handler(void);
extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
/* sysfs */
+
+struct device;
+
extern int cpuidle_add_interface(struct device *dev);
extern void cpuidle_remove_interface(struct device *dev);
-extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
-extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
-extern int cpuidle_add_sysfs(struct device *dev);
-extern void cpuidle_remove_sysfs(struct device *dev);
+extern int cpuidle_add_device_sysfs(struct cpuidle_device *device);
+extern void cpuidle_remove_device_sysfs(struct cpuidle_device *device);
+extern int cpuidle_add_sysfs(struct cpuidle_device *dev);
+extern void cpuidle_remove_sysfs(struct cpuidle_device *dev);
#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
bool cpuidle_state_is_coupled(struct cpuidle_device *dev,
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 87db3877fead..3af841fb397a 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -14,9 +14,10 @@
#include "cpuidle.h"
-static struct cpuidle_driver *cpuidle_curr_driver;
DEFINE_SPINLOCK(cpuidle_driver_lock);
-int cpuidle_driver_refcount;
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
+static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
static void set_power_states(struct cpuidle_driver *drv)
{
@@ -40,11 +41,15 @@ static void set_power_states(struct cpuidle_driver *drv)
drv->states[i].power_usage = -1 - i;
}
-/**
- * cpuidle_register_driver - registers a driver
- * @drv: the driver
- */
-int cpuidle_register_driver(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+{
+ drv->refcnt = 0;
+
+ if (!drv->power_specified)
+ set_power_states(drv);
+}
+
+static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
{
if (!drv || !drv->state_count)
return -EINVAL;
@@ -52,31 +57,145 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
if (cpuidle_disabled())
return -ENODEV;
- spin_lock(&cpuidle_driver_lock);
- if (cpuidle_curr_driver) {
- spin_unlock(&cpuidle_driver_lock);
+ if (__cpuidle_get_cpu_driver(cpu))
return -EBUSY;
+
+ __cpuidle_driver_init(drv);
+
+ __cpuidle_set_cpu_driver(drv, cpu);
+
+ return 0;
+}
+
+static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
+{
+ if (drv != __cpuidle_get_cpu_driver(cpu))
+ return;
+
+ if (!WARN_ON(drv->refcnt > 0))
+ __cpuidle_set_cpu_driver(NULL, cpu);
+}
+
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+
+static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+ per_cpu(cpuidle_drivers, cpu) = drv;
+}
+
+static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
+{
+ return per_cpu(cpuidle_drivers, cpu);
+}
+
+static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv)
+{
+ int cpu;
+ for_each_present_cpu(cpu)
+ __cpuidle_unregister_driver(drv, cpu);
+}
+
+static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
+{
+ int ret = 0;
+ int i, cpu;
+
+ for_each_present_cpu(cpu) {
+ ret = __cpuidle_register_driver(drv, cpu);
+ if (ret)
+ break;
}
- if (!drv->power_specified)
- set_power_states(drv);
+ if (ret)
+ for_each_present_cpu(i) {
+ if (i == cpu)
+ break;
+ __cpuidle_unregister_driver(drv, i);
+ }
- cpuidle_curr_driver = drv;
+ return ret;
+}
+
+int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+ int ret;
+
+ spin_lock(&cpuidle_driver_lock);
+ ret = __cpuidle_register_driver(drv, cpu);
spin_unlock(&cpuidle_driver_lock);
- return 0;
+ return ret;
+}
+
+void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+ spin_lock(&cpuidle_driver_lock);
+ __cpuidle_unregister_driver(drv, cpu);
+ spin_unlock(&cpuidle_driver_lock);
+}
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+ int ret;
+
+ spin_lock(&cpuidle_driver_lock);
+ ret = __cpuidle_register_all_cpu_driver(drv);
+ spin_unlock(&cpuidle_driver_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(cpuidle_register_driver);
/**
- * cpuidle_get_driver - return the current driver
+ * cpuidle_unregister_driver - unregisters a driver
+ * @drv: the driver
*/
-struct cpuidle_driver *cpuidle_get_driver(void)
+void cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+ spin_lock(&cpuidle_driver_lock);
+ __cpuidle_unregister_all_cpu_driver(drv);
+ spin_unlock(&cpuidle_driver_lock);
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+#else
+
+static struct cpuidle_driver *cpuidle_curr_driver;
+
+static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+ cpuidle_curr_driver = drv;
+}
+
+static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
{
return cpuidle_curr_driver;
}
-EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+ int ret, cpu;
+
+ cpu = get_cpu();
+ spin_lock(&cpuidle_driver_lock);
+ ret = __cpuidle_register_driver(drv, cpu);
+ spin_unlock(&cpuidle_driver_lock);
+ put_cpu();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cpuidle_register_driver);
/**
* cpuidle_unregister_driver - unregisters a driver
@@ -84,20 +203,50 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
*/
void cpuidle_unregister_driver(struct cpuidle_driver *drv)
{
- if (drv != cpuidle_curr_driver) {
- WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
- drv->name);
- return;
- }
+ int cpu;
+ cpu = get_cpu();
spin_lock(&cpuidle_driver_lock);
+ __cpuidle_unregister_driver(drv, cpu);
+ spin_unlock(&cpuidle_driver_lock);
+ put_cpu();
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+#endif
+
+/**
+ * cpuidle_get_driver - return the current driver
+ */
+struct cpuidle_driver *cpuidle_get_driver(void)
+{
+ struct cpuidle_driver *drv;
+ int cpu;
- if (!WARN_ON(cpuidle_driver_refcount > 0))
- cpuidle_curr_driver = NULL;
+ cpu = get_cpu();
+ drv = __cpuidle_get_cpu_driver(cpu);
+ put_cpu();
+ return drv;
+}
+EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_get_cpu_driver - return the driver tied with a cpu
+ */
+struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
+{
+ struct cpuidle_driver *drv;
+
+ if (!dev)
+ return NULL;
+
+ spin_lock(&cpuidle_driver_lock);
+ drv = __cpuidle_get_cpu_driver(dev->cpu);
spin_unlock(&cpuidle_driver_lock);
+
+ return drv;
}
-EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
struct cpuidle_driver *cpuidle_driver_ref(void)
{
@@ -105,8 +254,8 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
spin_lock(&cpuidle_driver_lock);
- drv = cpuidle_curr_driver;
- cpuidle_driver_refcount++;
+ drv = cpuidle_get_driver();
+ drv->refcnt++;
spin_unlock(&cpuidle_driver_lock);
return drv;
@@ -114,10 +263,12 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
void cpuidle_driver_unref(void)
{
+ struct cpuidle_driver *drv = cpuidle_get_driver();
+
spin_lock(&cpuidle_driver_lock);
- if (!WARN_ON(cpuidle_driver_refcount <= 0))
- cpuidle_driver_refcount--;
+ if (drv && !WARN_ON(drv->refcnt <= 0))
+ drv->refcnt--;
spin_unlock(&cpuidle_driver_lock);
}
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 5b1f2c372c1f..bd40b943b6db 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -28,6 +28,13 @@
#define MAX_INTERESTING 50000
#define STDDEV_THRESH 400
+/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */
+#define MAX_DEVIATION 60
+
+static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer);
+static DEFINE_PER_CPU(int, hrtimer_status);
+/* menu hrtimer mode */
+enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};
/*
* Concepts and ideas behind the menu governor
@@ -109,6 +116,13 @@
*
*/
+/*
+ * The C-state residency is so long that is is worthwhile to exit
+ * from the shallow C-state and re-enter into a deeper C-state.
+ */
+static unsigned int perfect_cstate_ms __read_mostly = 30;
+module_param(perfect_cstate_ms, uint, 0000);
+
struct menu_device {
int last_state_idx;
int needs_update;
@@ -191,40 +205,102 @@ static u64 div_round64(u64 dividend, u32 divisor)
return div_u64(dividend + (divisor / 2), divisor);
}
+/* Cancel the hrtimer if it is not triggered yet */
+void menu_hrtimer_cancel(void)
+{
+ int cpu = smp_processor_id();
+ struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
+
+ /* The timer is still not time out*/
+ if (per_cpu(hrtimer_status, cpu)) {
+ hrtimer_cancel(hrtmr);
+ per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+ }
+}
+EXPORT_SYMBOL_GPL(menu_hrtimer_cancel);
+
+/* Call back for hrtimer is triggered */
+static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer)
+{
+ int cpu = smp_processor_id();
+ struct menu_device *data = &per_cpu(menu_devices, cpu);
+
+ /* In general case, the expected residency is much larger than
+ * deepest C-state target residency, but prediction logic still
+ * predicts a small predicted residency, so the prediction
+ * history is totally broken if the timer is triggered.
+ * So reset the correction factor.
+ */
+ if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL)
+ data->correction_factor[data->bucket] = RESOLUTION * DECAY;
+
+ per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;
+
+ return HRTIMER_NORESTART;
+}
+
/*
* Try detecting repeating patterns by keeping track of the last 8
* intervals, and checking if the standard deviation of that set
* of points is below a threshold. If it is... then use the
* average of these 8 points as the estimated value.
*/
-static void detect_repeating_patterns(struct menu_device *data)
+static u32 get_typical_interval(struct menu_device *data)
{
- int i;
- uint64_t avg = 0;
- uint64_t stddev = 0; /* contains the square of the std deviation */
-
- /* first calculate average and standard deviation of the past */
- for (i = 0; i < INTERVALS; i++)
- avg += data->intervals[i];
- avg = avg / INTERVALS;
+ int i = 0, divisor = 0;
+ uint64_t max = 0, avg = 0, stddev = 0;
+ int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */
+ unsigned int ret = 0;
- /* if the avg is beyond the known next tick, it's worthless */
- if (avg > data->expected_us)
- return;
+again:
- for (i = 0; i < INTERVALS; i++)
- stddev += (data->intervals[i] - avg) *
- (data->intervals[i] - avg);
-
- stddev = stddev / INTERVALS;
+ /* first calculate average and standard deviation of the past */
+ max = avg = divisor = stddev = 0;
+ for (i = 0; i < INTERVALS; i++) {
+ int64_t value = data->intervals[i];
+ if (value <= thresh) {
+ avg += value;
+ divisor++;
+ if (value > max)
+ max = value;
+ }
+ }
+ do_div(avg, divisor);
+ for (i = 0; i < INTERVALS; i++) {
+ int64_t value = data->intervals[i];
+ if (value <= thresh) {
+ int64_t diff = value - avg;
+ stddev += diff * diff;
+ }
+ }
+ do_div(stddev, divisor);
+ stddev = int_sqrt(stddev);
/*
- * now.. if stddev is small.. then assume we have a
- * repeating pattern and predict we keep doing this.
+ * If we have outliers to the upside in our distribution, discard
+ * those by setting the threshold to exclude these outliers, then
+ * calculate the average and standard deviation again. Once we get
+ * down to the bottom 3/4 of our samples, stop excluding samples.
+ *
+ * This can deal with workloads that have long pauses interspersed
+ * with sporadic activity with a bunch of short pauses.
+ *
+ * The typical interval is obtained when standard deviation is small
+ * or standard deviation is small compared to the average interval.
*/
-
- if (avg && stddev < STDDEV_THRESH)
+ if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
+ || stddev <= 20) {
data->predicted_us = avg;
+ ret = 1;
+ return ret;
+
+ } else if ((divisor * 4) > INTERVALS * 3) {
+ /* Exclude the max interval */
+ thresh = max - 1;
+ goto again;
+ }
+
+ return ret;
}
/**
@@ -240,6 +316,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
int i;
int multiplier;
struct timespec t;
+ int repeat = 0, low_predicted = 0;
+ int cpu = smp_processor_id();
+ struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu);
if (data->needs_update) {
menu_update(drv, dev);
@@ -274,7 +353,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket],
RESOLUTION * DECAY);
- detect_repeating_patterns(data);
+ repeat = get_typical_interval(data);
/*
* We want to default to C1 (hlt), not to busy polling
@@ -295,8 +374,10 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
if (s->disabled || su->disable)
continue;
- if (s->target_residency > data->predicted_us)
+ if (s->target_residency > data->predicted_us) {
+ low_predicted = 1;
continue;
+ }
if (s->exit_latency > latency_req)
continue;
if (s->exit_latency * multiplier > data->predicted_us)
@@ -309,6 +390,44 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
}
}
+ /* not deepest C-state chosen for low predicted residency */
+ if (low_predicted) {
+ unsigned int timer_us = 0;
+ unsigned int perfect_us = 0;
+
+ /*
+ * Set a timer to detect whether this sleep is much
+ * longer than repeat mode predicted. If the timer
+ * triggers, the code will evaluate whether to put
+ * the CPU into a deeper C-state.
+ * The timer is cancelled on CPU wakeup.
+ */
+ timer_us = 2 * (data->predicted_us + MAX_DEVIATION);
+
+ perfect_us = perfect_cstate_ms * 1000;
+
+ if (repeat && (4 * timer_us < data->expected_us)) {
+ RCU_NONIDLE(hrtimer_start(hrtmr,
+ ns_to_ktime(1000 * timer_us),
+ HRTIMER_MODE_REL_PINNED));
+ /* In repeat case, menu hrtimer is started */
+ per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT;
+ } else if (perfect_us < data->expected_us) {
+ /*
+ * The next timer is long. This could be because
+ * we did not make a useful prediction.
+ * In that case, it makes sense to re-enter
+ * into a deeper C-state after some time.
+ */
+ RCU_NONIDLE(hrtimer_start(hrtmr,
+ ns_to_ktime(1000 * timer_us),
+ HRTIMER_MODE_REL_PINNED));
+ /* In general case, menu hrtimer is started */
+ per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL;
+ }
+
+ }
+
return data->last_state_idx;
}
@@ -399,6 +518,9 @@ static int menu_enable_device(struct cpuidle_driver *drv,
struct cpuidle_device *dev)
{
struct menu_device *data = &per_cpu(menu_devices, dev->cpu);
+ struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu);
+ hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ t->function = menu_hrtimer_notify;
memset(data, 0, sizeof(struct menu_device));
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 5f809e337b89..340942946106 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/capability.h>
+#include <linux/device.h>
#include "cpuidle.h"
@@ -297,6 +298,13 @@ static struct attribute *cpuidle_state_default_attrs[] = {
NULL
};
+struct cpuidle_state_kobj {
+ struct cpuidle_state *state;
+ struct cpuidle_state_usage *state_usage;
+ struct completion kobj_unregister;
+ struct kobject kobj;
+};
+
#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
@@ -356,17 +364,17 @@ static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
}
/**
- * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
+ * cpuidle_add_state_sysfs - adds cpuidle states sysfs attributes
* @device: the target device
*/
-int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
{
int i, ret = -ENOMEM;
struct cpuidle_state_kobj *kobj;
- struct cpuidle_driver *drv = cpuidle_get_driver();
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
/* state statistics */
- for (i = 0; i < device->state_count; i++) {
+ for (i = 0; i < drv->state_count; i++) {
kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
if (!kobj)
goto error_state;
@@ -374,8 +382,8 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
kobj->state_usage = &device->states_usage[i];
init_completion(&kobj->kobj_unregister);
- ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
- "state%d", i);
+ ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
+ &device->kobj, "state%d", i);
if (ret) {
kfree(kobj);
goto error_state;
@@ -393,10 +401,10 @@ error_state:
}
/**
- * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
+ * cpuidle_remove_driver_sysfs - removes the cpuidle states sysfs attributes
* @device: the target device
*/
-void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
+static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
{
int i;
@@ -404,17 +412,179 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
cpuidle_free_state_kobj(device, i);
}
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+#define kobj_to_driver_kobj(k) container_of(k, struct cpuidle_driver_kobj, kobj)
+#define attr_to_driver_attr(a) container_of(a, struct cpuidle_driver_attr, attr)
+
+#define define_one_driver_ro(_name, show) \
+ static struct cpuidle_driver_attr attr_driver_##_name = \
+ __ATTR(_name, 0644, show, NULL)
+
+struct cpuidle_driver_kobj {
+ struct cpuidle_driver *drv;
+ struct completion kobj_unregister;
+ struct kobject kobj;
+};
+
+struct cpuidle_driver_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct cpuidle_driver *, char *);
+ ssize_t (*store)(struct cpuidle_driver *, const char *, size_t);
+};
+
+static ssize_t show_driver_name(struct cpuidle_driver *drv, char *buf)
+{
+ ssize_t ret;
+
+ spin_lock(&cpuidle_driver_lock);
+ ret = sprintf(buf, "%s\n", drv ? drv->name : "none");
+ spin_unlock(&cpuidle_driver_lock);
+
+ return ret;
+}
+
+static void cpuidle_driver_sysfs_release(struct kobject *kobj)
+{
+ struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+ complete(&driver_kobj->kobj_unregister);
+}
+
+static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr,
+ char * buf)
+{
+ int ret = -EIO;
+ struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+ struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+ if (dattr->show)
+ ret = dattr->show(driver_kobj->drv, buf);
+
+ return ret;
+}
+
+static ssize_t cpuidle_driver_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t size)
+{
+ int ret = -EIO;
+ struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+ struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+ if (dattr->store)
+ ret = dattr->store(driver_kobj->drv, buf, size);
+
+ return ret;
+}
+
+define_one_driver_ro(name, show_driver_name);
+
+static const struct sysfs_ops cpuidle_driver_sysfs_ops = {
+ .show = cpuidle_driver_show,
+ .store = cpuidle_driver_store,
+};
+
+static struct attribute *cpuidle_driver_default_attrs[] = {
+ &attr_driver_name.attr,
+ NULL
+};
+
+static struct kobj_type ktype_driver_cpuidle = {
+ .sysfs_ops = &cpuidle_driver_sysfs_ops,
+ .default_attrs = cpuidle_driver_default_attrs,
+ .release = cpuidle_driver_sysfs_release,
+};
+
+/**
+ * cpuidle_add_driver_sysfs - adds the driver name sysfs attribute
+ * @device: the target device
+ */
+static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+ struct cpuidle_driver_kobj *kdrv;
+ struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+ int ret;
+
+ kdrv = kzalloc(sizeof(*kdrv), GFP_KERNEL);
+ if (!kdrv)
+ return -ENOMEM;
+
+ kdrv->drv = drv;
+ init_completion(&kdrv->kobj_unregister);
+
+ ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
+ &dev->kobj, "driver");
+ if (ret) {
+ kfree(kdrv);
+ return ret;
+ }
+
+ kobject_uevent(&kdrv->kobj, KOBJ_ADD);
+ dev->kobj_driver = kdrv;
+
+ return ret;
+}
+
+/**
+ * cpuidle_remove_driver_sysfs - removes the driver name sysfs attribute
+ * @device: the target device
+ */
+static void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+ struct cpuidle_driver_kobj *kdrv = dev->kobj_driver;
+ kobject_put(&kdrv->kobj);
+ wait_for_completion(&kdrv->kobj_unregister);
+ kfree(kdrv);
+}
+#else
+static inline int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+ return 0;
+}
+
+static inline void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+ ;
+}
+#endif
+
+/**
+ * cpuidle_add_device_sysfs - adds device specific sysfs attributes
+ * @device: the target device
+ */
+int cpuidle_add_device_sysfs(struct cpuidle_device *device)
+{
+ int ret;
+
+ ret = cpuidle_add_state_sysfs(device);
+ if (ret)
+ return ret;
+
+ ret = cpuidle_add_driver_sysfs(device);
+ if (ret)
+ cpuidle_remove_state_sysfs(device);
+ return ret;
+}
+
+/**
+ * cpuidle_remove_device_sysfs : removes device specific sysfs attributes
+ * @device : the target device
+ */
+void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
+{
+ cpuidle_remove_driver_sysfs(device);
+ cpuidle_remove_state_sysfs(device);
+}
+
/**
* cpuidle_add_sysfs - creates a sysfs instance for the target device
* @dev: the target device
*/
-int cpuidle_add_sysfs(struct device *cpu_dev)
+int cpuidle_add_sysfs(struct cpuidle_device *dev)
{
- int cpu = cpu_dev->id;
- struct cpuidle_device *dev;
+ struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu);
int error;
- dev = per_cpu(cpuidle_devices, cpu);
+ init_completion(&dev->kobj_unregister);
+
error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
"cpuidle");
if (!error)
@@ -426,11 +596,8 @@ int cpuidle_add_sysfs(struct device *cpu_dev)
* cpuidle_remove_sysfs - deletes a sysfs instance on the target device
* @dev: the target device
*/
-void cpuidle_remove_sysfs(struct device *cpu_dev)
+void cpuidle_remove_sysfs(struct cpuidle_device *dev)
{
- int cpu = cpu_dev->id;
- struct cpuidle_device *dev;
-
- dev = per_cpu(cpuidle_devices, cpu);
kobject_put(&dev->kobj);
+ wait_for_completion(&dev->kobj_unregister);
}
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 308c7fb92a60..f6644f59fd9d 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -224,7 +224,7 @@ config CRYPTO_DEV_TALITOS
config CRYPTO_DEV_IXP4XX
tristate "Driver for IXP4xx crypto hardware acceleration"
- depends on ARCH_IXP4XX
+ depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE
select CRYPTO_DES
select CRYPTO_ALGAPI
select CRYPTO_AUTHENC
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 8f3f74ce8c7f..21180d6cad6e 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -750,12 +750,12 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt,
}
if (cipher_cfg & MOD_AES) {
switch (key_len) {
- case 16: keylen_cfg = MOD_AES128 | KEYLEN_128; break;
- case 24: keylen_cfg = MOD_AES192 | KEYLEN_192; break;
- case 32: keylen_cfg = MOD_AES256 | KEYLEN_256; break;
- default:
- *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- return -EINVAL;
+ case 16: keylen_cfg = MOD_AES128; break;
+ case 24: keylen_cfg = MOD_AES192; break;
+ case 32: keylen_cfg = MOD_AES256; break;
+ default:
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
}
cipher_cfg |= keylen_cfg;
} else if (cipher_cfg & MOD_3DES) {
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index f6b0a6e2ea50..0f079be13305 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -30,7 +30,7 @@ if PM_DEVFREQ
comment "DEVFREQ Governors"
config DEVFREQ_GOV_SIMPLE_ONDEMAND
- bool "Simple Ondemand"
+ tristate "Simple Ondemand"
help
Chooses frequency based on the recent load on the device. Works
similar as ONDEMAND governor of CPUFREQ does. A device with
@@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND
values to the governor with data field at devfreq_add_device().
config DEVFREQ_GOV_PERFORMANCE
- bool "Performance"
+ tristate "Performance"
help
Sets the frequency at the maximum available frequency.
This governor always returns UINT_MAX as frequency so that
@@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE
at any time.
config DEVFREQ_GOV_POWERSAVE
- bool "Powersave"
+ tristate "Powersave"
help
Sets the frequency at the minimum available frequency.
This governor always returns 0 as frequency so that
@@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE
at any time.
config DEVFREQ_GOV_USERSPACE
- bool "Userspace"
+ tristate "Userspace"
help
Sets the frequency at the user specified one.
This governor returns the user configured frequency if there
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index b146d76f04cf..53766f39aadd 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -27,21 +27,17 @@
#include <linux/hrtimer.h>
#include "governor.h"
-struct class *devfreq_class;
+static struct class *devfreq_class;
/*
- * devfreq_work periodically monitors every registered device.
- * The minimum polling interval is one jiffy. The polling interval is
- * determined by the minimum polling period among all polling devfreq
- * devices. The resolution of polling interval is one jiffy.
+ * devfreq core provides delayed work based load monitoring helper
+ * functions. Governors can use these or can implement their own
+ * monitoring mechanism.
*/
-static bool polling;
static struct workqueue_struct *devfreq_wq;
-static struct delayed_work devfreq_work;
-
-/* wait removing if this is to be removed */
-static struct devfreq *wait_remove_device;
+/* The list of all device-devfreq governors */
+static LIST_HEAD(devfreq_governor_list);
/* The list of all device-devfreq */
static LIST_HEAD(devfreq_list);
static DEFINE_MUTEX(devfreq_list_lock);
@@ -73,6 +69,79 @@ static struct devfreq *find_device_devfreq(struct device *dev)
}
/**
+ * devfreq_get_freq_level() - Lookup freq_table for the frequency
+ * @devfreq: the devfreq instance
+ * @freq: the target frequency
+ */
+static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+{
+ int lev;
+
+ for (lev = 0; lev < devfreq->profile->max_state; lev++)
+ if (freq == devfreq->profile->freq_table[lev])
+ return lev;
+
+ return -EINVAL;
+}
+
+/**
+ * devfreq_update_status() - Update statistics of devfreq behavior
+ * @devfreq: the devfreq instance
+ * @freq: the update target frequency
+ */
+static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
+{
+ int lev, prev_lev;
+ unsigned long cur_time;
+
+ lev = devfreq_get_freq_level(devfreq, freq);
+ if (lev < 0)
+ return lev;
+
+ cur_time = jiffies;
+ devfreq->time_in_state[lev] +=
+ cur_time - devfreq->last_stat_updated;
+ if (freq != devfreq->previous_freq) {
+ prev_lev = devfreq_get_freq_level(devfreq,
+ devfreq->previous_freq);
+ devfreq->trans_table[(prev_lev *
+ devfreq->profile->max_state) + lev]++;
+ devfreq->total_trans++;
+ }
+ devfreq->last_stat_updated = cur_time;
+
+ return 0;
+}
+
+/**
+ * find_devfreq_governor() - find devfreq governor from name
+ * @name: name of the governor
+ *
+ * Search the list of devfreq governors and return the matched
+ * governor's pointer. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq_governor *find_devfreq_governor(const char *name)
+{
+ struct devfreq_governor *tmp_governor;
+
+ if (unlikely(IS_ERR_OR_NULL(name))) {
+ pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+ WARN(!mutex_is_locked(&devfreq_list_lock),
+ "devfreq_list_lock must be locked.");
+
+ list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
+ if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+ return tmp_governor;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+/* Load monitoring helper functions for governors use */
+
+/**
* update_devfreq() - Reevaluate the device and configure frequency.
* @devfreq: the devfreq instance.
*
@@ -90,6 +159,9 @@ int update_devfreq(struct devfreq *devfreq)
return -EINVAL;
}
+ if (!devfreq->governor)
+ return -EINVAL;
+
/* Reevaluate the proper frequency */
err = devfreq->governor->get_target_freq(devfreq, &freq);
if (err)
@@ -116,16 +188,173 @@ int update_devfreq(struct devfreq *devfreq)
if (err)
return err;
+ if (devfreq->profile->freq_table)
+ if (devfreq_update_status(devfreq, freq))
+ dev_err(&devfreq->dev,
+ "Couldn't update frequency transition information.\n");
+
devfreq->previous_freq = freq;
return err;
}
+EXPORT_SYMBOL(update_devfreq);
+
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work: the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+ int err;
+ struct devfreq *devfreq = container_of(work,
+ struct devfreq, work.work);
+
+ mutex_lock(&devfreq->lock);
+ err = update_devfreq(devfreq);
+ if (err)
+ dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
+
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ mutex_unlock(&devfreq->lock);
+}
+
+/**
+ * devfreq_monitor_start() - Start load monitoring of devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function for starting devfreq device load monitoing. By
+ * default delayed work based monitoring is supported. Function
+ * to be called from governor in response to DEVFREQ_GOV_START
+ * event when device is added to devfreq framework.
+ */
+void devfreq_monitor_start(struct devfreq *devfreq)
+{
+ INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+ if (devfreq->profile->polling_ms)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+}
+EXPORT_SYMBOL(devfreq_monitor_start);
+
+/**
+ * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to stop devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_STOP
+ * event when device is removed from devfreq framework.
+ */
+void devfreq_monitor_stop(struct devfreq *devfreq)
+{
+ cancel_delayed_work_sync(&devfreq->work);
+}
+EXPORT_SYMBOL(devfreq_monitor_stop);
+
+/**
+ * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to suspend devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_SUSPEND
+ * event or when polling interval is set to zero.
+ *
+ * Note: Though this function is same as devfreq_monitor_stop(),
+ * intentionally kept separate to provide hooks for collecting
+ * transition statistics.
+ */
+void devfreq_monitor_suspend(struct devfreq *devfreq)
+{
+ mutex_lock(&devfreq->lock);
+ if (devfreq->stop_polling) {
+ mutex_unlock(&devfreq->lock);
+ return;
+ }
+
+ devfreq->stop_polling = true;
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+}
+EXPORT_SYMBOL(devfreq_monitor_suspend);
+
+/**
+ * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to resume devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_RESUME
+ * event or when polling interval is set to non-zero.
+ */
+void devfreq_monitor_resume(struct devfreq *devfreq)
+{
+ mutex_lock(&devfreq->lock);
+ if (!devfreq->stop_polling)
+ goto out;
+
+ if (!delayed_work_pending(&devfreq->work) &&
+ devfreq->profile->polling_ms)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ devfreq->stop_polling = false;
+
+out:
+ mutex_unlock(&devfreq->lock);
+}
+EXPORT_SYMBOL(devfreq_monitor_resume);
+
+/**
+ * devfreq_interval_update() - Update device devfreq monitoring interval
+ * @devfreq: the devfreq instance.
+ * @delay: new polling interval to be set.
+ *
+ * Helper function to set new load monitoring polling interval. Function
+ * to be called from governor in response to DEVFREQ_GOV_INTERVAL event.
+ */
+void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
+{
+ unsigned int cur_delay = devfreq->profile->polling_ms;
+ unsigned int new_delay = *delay;
+
+ mutex_lock(&devfreq->lock);
+ devfreq->profile->polling_ms = new_delay;
+
+ if (devfreq->stop_polling)
+ goto out;
+
+ /* if new delay is zero, stop polling */
+ if (!new_delay) {
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+ return;
+ }
+
+ /* if current delay is zero, start polling with new delay */
+ if (!cur_delay) {
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ goto out;
+ }
+
+ /* if current delay is greater than new delay, restart polling */
+ if (cur_delay > new_delay) {
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+ mutex_lock(&devfreq->lock);
+ if (!devfreq->stop_polling)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ }
+out:
+ mutex_unlock(&devfreq->lock);
+}
+EXPORT_SYMBOL(devfreq_interval_update);
/**
* devfreq_notifier_call() - Notify that the device frequency requirements
* has been changed out of devfreq framework.
- * @nb the notifier_block (supposed to be devfreq->nb)
- * @type not used
- * @devp not used
+ * @nb: the notifier_block (supposed to be devfreq->nb)
+ * @type: not used
+ * @devp: not used
*
* Called by a notifier that uses devfreq->nb.
*/
@@ -143,59 +372,34 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
}
/**
- * _remove_devfreq() - Remove devfreq from the device.
+ * _remove_devfreq() - Remove devfreq from the list and release its resources.
* @devfreq: the devfreq struct
* @skip: skip calling device_unregister().
- *
- * Note that the caller should lock devfreq->lock before calling
- * this. _remove_devfreq() will unlock it and free devfreq
- * internally. devfreq_list_lock should be locked by the caller
- * as well (not relased at return)
- *
- * Lock usage:
- * devfreq->lock: locked before call.
- * unlocked at return (and freed)
- * devfreq_list_lock: locked before call.
- * kept locked at return.
- * if devfreq is centrally polled.
- *
- * Freed memory:
- * devfreq
*/
static void _remove_devfreq(struct devfreq *devfreq, bool skip)
{
- if (!mutex_is_locked(&devfreq->lock)) {
- WARN(true, "devfreq->lock must be locked by the caller.\n");
- return;
- }
- if (!devfreq->governor->no_central_polling &&
- !mutex_is_locked(&devfreq_list_lock)) {
- WARN(true, "devfreq_list_lock must be locked by the caller.\n");
+ mutex_lock(&devfreq_list_lock);
+ if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
+ mutex_unlock(&devfreq_list_lock);
+ dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
return;
}
+ list_del(&devfreq->node);
+ mutex_unlock(&devfreq_list_lock);
- if (devfreq->being_removed)
- return;
-
- devfreq->being_removed = true;
+ if (devfreq->governor)
+ devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
if (devfreq->profile->exit)
devfreq->profile->exit(devfreq->dev.parent);
- if (devfreq->governor->exit)
- devfreq->governor->exit(devfreq);
-
if (!skip && get_device(&devfreq->dev)) {
device_unregister(&devfreq->dev);
put_device(&devfreq->dev);
}
- if (!devfreq->governor->no_central_polling)
- list_del(&devfreq->node);
-
- mutex_unlock(&devfreq->lock);
mutex_destroy(&devfreq->lock);
-
kfree(devfreq);
}
@@ -210,163 +414,39 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
static void devfreq_dev_release(struct device *dev)
{
struct devfreq *devfreq = to_devfreq(dev);
- bool central_polling = !devfreq->governor->no_central_polling;
-
- /*
- * If devfreq_dev_release() was called by device_unregister() of
- * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
- * being_removed is already set. This also partially checks the case
- * where devfreq_dev_release() is called from a thread other than
- * the one called _remove_devfreq(); however, this case is
- * dealt completely with another following being_removed check.
- *
- * Because being_removed is never being
- * unset, we do not need to worry about race conditions on
- * being_removed.
- */
- if (devfreq->being_removed)
- return;
-
- if (central_polling)
- mutex_lock(&devfreq_list_lock);
-
- mutex_lock(&devfreq->lock);
- /*
- * Check being_removed flag again for the case where
- * devfreq_dev_release() was called in a thread other than the one
- * possibly called _remove_devfreq().
- */
- if (devfreq->being_removed) {
- mutex_unlock(&devfreq->lock);
- goto out;
- }
-
- /* devfreq->lock is unlocked and removed in _removed_devfreq() */
_remove_devfreq(devfreq, true);
-
-out:
- if (central_polling)
- mutex_unlock(&devfreq_list_lock);
-}
-
-/**
- * devfreq_monitor() - Periodically poll devfreq objects.
- * @work: the work struct used to run devfreq_monitor periodically.
- *
- */
-static void devfreq_monitor(struct work_struct *work)
-{
- static unsigned long last_polled_at;
- struct devfreq *devfreq, *tmp;
- int error;
- unsigned long jiffies_passed;
- unsigned long next_jiffies = ULONG_MAX, now = jiffies;
- struct device *dev;
-
- /* Initially last_polled_at = 0, polling every device at bootup */
- jiffies_passed = now - last_polled_at;
- last_polled_at = now;
- if (jiffies_passed == 0)
- jiffies_passed = 1;
-
- mutex_lock(&devfreq_list_lock);
- list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
- mutex_lock(&devfreq->lock);
- dev = devfreq->dev.parent;
-
- /* Do not remove tmp for a while */
- wait_remove_device = tmp;
-
- if (devfreq->governor->no_central_polling ||
- devfreq->next_polling == 0) {
- mutex_unlock(&devfreq->lock);
- continue;
- }
- mutex_unlock(&devfreq_list_lock);
-
- /*
- * Reduce more next_polling if devfreq_wq took an extra
- * delay. (i.e., CPU has been idled.)
- */
- if (devfreq->next_polling <= jiffies_passed) {
- error = update_devfreq(devfreq);
-
- /* Remove a devfreq with an error. */
- if (error && error != -EAGAIN) {
-
- dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
- error, devfreq->governor->name);
-
- /*
- * Unlock devfreq before locking the list
- * in order to avoid deadlock with
- * find_device_devfreq or others
- */
- mutex_unlock(&devfreq->lock);
- mutex_lock(&devfreq_list_lock);
- /* Check if devfreq is already removed */
- if (IS_ERR(find_device_devfreq(dev)))
- continue;
- mutex_lock(&devfreq->lock);
- /* This unlocks devfreq->lock and free it */
- _remove_devfreq(devfreq, false);
- continue;
- }
- devfreq->next_polling = devfreq->polling_jiffies;
- } else {
- devfreq->next_polling -= jiffies_passed;
- }
-
- if (devfreq->next_polling)
- next_jiffies = (next_jiffies > devfreq->next_polling) ?
- devfreq->next_polling : next_jiffies;
-
- mutex_unlock(&devfreq->lock);
- mutex_lock(&devfreq_list_lock);
- }
- wait_remove_device = NULL;
- mutex_unlock(&devfreq_list_lock);
-
- if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
- } else {
- polling = false;
- }
}
/**
* devfreq_add_device() - Add devfreq feature to the device
* @dev: the device to add devfreq feature.
* @profile: device-specific profile to run devfreq.
- * @governor: the policy to choose frequency.
+ * @governor_name: name of the policy to choose frequency.
* @data: private data for the governor. The devfreq framework does not
* touch this value.
*/
struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- const struct devfreq_governor *governor,
+ const char *governor_name,
void *data)
{
struct devfreq *devfreq;
+ struct devfreq_governor *governor;
int err = 0;
- if (!dev || !profile || !governor) {
+ if (!dev || !profile || !governor_name) {
dev_err(dev, "%s: Invalid parameters.\n", __func__);
return ERR_PTR(-EINVAL);
}
-
- if (!governor->no_central_polling) {
- mutex_lock(&devfreq_list_lock);
- devfreq = find_device_devfreq(dev);
- mutex_unlock(&devfreq_list_lock);
- if (!IS_ERR(devfreq)) {
- dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
- err = -EINVAL;
- goto err_out;
- }
+ mutex_lock(&devfreq_list_lock);
+ devfreq = find_device_devfreq(dev);
+ mutex_unlock(&devfreq_list_lock);
+ if (!IS_ERR(devfreq)) {
+ dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+ err = -EINVAL;
+ goto err_out;
}
devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
@@ -383,92 +463,316 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->dev.class = devfreq_class;
devfreq->dev.release = devfreq_dev_release;
devfreq->profile = profile;
- devfreq->governor = governor;
+ strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
devfreq->previous_freq = profile->initial_freq;
devfreq->data = data;
- devfreq->next_polling = devfreq->polling_jiffies
- = msecs_to_jiffies(devfreq->profile->polling_ms);
devfreq->nb.notifier_call = devfreq_notifier_call;
+ devfreq->trans_table = devm_kzalloc(dev, sizeof(unsigned int) *
+ devfreq->profile->max_state *
+ devfreq->profile->max_state,
+ GFP_KERNEL);
+ devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
+ devfreq->profile->max_state,
+ GFP_KERNEL);
+ devfreq->last_stat_updated = jiffies;
+
dev_set_name(&devfreq->dev, dev_name(dev));
err = device_register(&devfreq->dev);
if (err) {
put_device(&devfreq->dev);
+ mutex_unlock(&devfreq->lock);
goto err_dev;
}
- if (governor->init)
- err = governor->init(devfreq);
- if (err)
- goto err_init;
-
mutex_unlock(&devfreq->lock);
- if (governor->no_central_polling)
- goto out;
-
mutex_lock(&devfreq_list_lock);
-
list_add(&devfreq->node, &devfreq_list);
- if (devfreq_wq && devfreq->next_polling && !polling) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work,
- devfreq->next_polling);
- }
+ governor = find_devfreq_governor(devfreq->governor_name);
+ if (!IS_ERR(governor))
+ devfreq->governor = governor;
+ if (devfreq->governor)
+ err = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_START, NULL);
mutex_unlock(&devfreq_list_lock);
-out:
+ if (err) {
+ dev_err(dev, "%s: Unable to start governor for the device\n",
+ __func__);
+ goto err_init;
+ }
+
return devfreq;
err_init:
+ list_del(&devfreq->node);
device_unregister(&devfreq->dev);
err_dev:
- mutex_unlock(&devfreq->lock);
kfree(devfreq);
err_out:
return ERR_PTR(err);
}
+EXPORT_SYMBOL(devfreq_add_device);
/**
* devfreq_remove_device() - Remove devfreq feature from a device.
- * @devfreq the devfreq instance to be removed
+ * @devfreq: the devfreq instance to be removed
*/
int devfreq_remove_device(struct devfreq *devfreq)
{
- bool central_polling;
+ if (!devfreq)
+ return -EINVAL;
+
+ _remove_devfreq(devfreq, false);
+ return 0;
+}
+EXPORT_SYMBOL(devfreq_remove_device);
+
+/**
+ * devfreq_suspend_device() - Suspend devfreq of a device.
+ * @devfreq: the devfreq instance to be suspended
+ */
+int devfreq_suspend_device(struct devfreq *devfreq)
+{
if (!devfreq)
return -EINVAL;
- central_polling = !devfreq->governor->no_central_polling;
+ if (!devfreq->governor)
+ return 0;
+
+ return devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_SUSPEND, NULL);
+}
+EXPORT_SYMBOL(devfreq_suspend_device);
+
+/**
+ * devfreq_resume_device() - Resume devfreq of a device.
+ * @devfreq: the devfreq instance to be resumed
+ */
+int devfreq_resume_device(struct devfreq *devfreq)
+{
+ if (!devfreq)
+ return -EINVAL;
+
+ if (!devfreq->governor)
+ return 0;
+
+ return devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_RESUME, NULL);
+}
+EXPORT_SYMBOL(devfreq_resume_device);
+
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor: the devfreq governor to be added
+ */
+int devfreq_add_governor(struct devfreq_governor *governor)
+{
+ struct devfreq_governor *g;
+ struct devfreq *devfreq;
+ int err = 0;
+
+ if (!governor) {
+ pr_err("%s: Invalid parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&devfreq_list_lock);
+ g = find_devfreq_governor(governor->name);
+ if (!IS_ERR(g)) {
+ pr_err("%s: governor %s already registered\n", __func__,
+ g->name);
+ err = -EINVAL;
+ goto err_out;
+ }
- if (central_polling) {
- mutex_lock(&devfreq_list_lock);
- while (wait_remove_device == devfreq) {
- mutex_unlock(&devfreq_list_lock);
- schedule();
- mutex_lock(&devfreq_list_lock);
+ list_add(&governor->node, &devfreq_governor_list);
+
+ list_for_each_entry(devfreq, &devfreq_list, node) {
+ int ret = 0;
+ struct device *dev = devfreq->dev.parent;
+
+ if (!strncmp(devfreq->governor_name, governor->name,
+ DEVFREQ_NAME_LEN)) {
+ /* The following should never occur */
+ if (devfreq->governor) {
+ dev_warn(dev,
+ "%s: Governor %s already present\n",
+ __func__, devfreq->governor->name);
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev,
+ "%s: Governor %s stop = %d\n",
+ __func__,
+ devfreq->governor->name, ret);
+ }
+ /* Fall through */
+ }
+ devfreq->governor = governor;
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s start=%d\n",
+ __func__, devfreq->governor->name,
+ ret);
+ }
}
}
- mutex_lock(&devfreq->lock);
- _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+err_out:
+ mutex_unlock(&devfreq_list_lock);
- if (central_polling)
- mutex_unlock(&devfreq_list_lock);
+ return err;
+}
+EXPORT_SYMBOL(devfreq_add_governor);
- return 0;
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @governor: the devfreq governor to be removed
+ */
+int devfreq_remove_governor(struct devfreq_governor *governor)
+{
+ struct devfreq_governor *g;
+ struct devfreq *devfreq;
+ int err = 0;
+
+ if (!governor) {
+ pr_err("%s: Invalid parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&devfreq_list_lock);
+ g = find_devfreq_governor(governor->name);
+ if (IS_ERR(g)) {
+ pr_err("%s: governor %s not registered\n", __func__,
+ governor->name);
+ err = PTR_ERR(g);
+ goto err_out;
+ }
+ list_for_each_entry(devfreq, &devfreq_list, node) {
+ int ret;
+ struct device *dev = devfreq->dev.parent;
+
+ if (!strncmp(devfreq->governor_name, governor->name,
+ DEVFREQ_NAME_LEN)) {
+ /* we should have a devfreq governor! */
+ if (!devfreq->governor) {
+ dev_warn(dev, "%s: Governor %s NOT present\n",
+ __func__, governor->name);
+ continue;
+ /* Fall through */
+ }
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s stop=%d\n",
+ __func__, devfreq->governor->name,
+ ret);
+ }
+ devfreq->governor = NULL;
+ }
+ }
+
+ list_del(&governor->node);
+err_out:
+ mutex_unlock(&devfreq_list_lock);
+
+ return err;
}
+EXPORT_SYMBOL(devfreq_remove_governor);
static ssize_t show_governor(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ if (!to_devfreq(dev)->governor)
+ return -EINVAL;
+
return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
}
+static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct devfreq *df = to_devfreq(dev);
+ int ret;
+ char str_governor[DEVFREQ_NAME_LEN + 1];
+ struct devfreq_governor *governor;
+
+ ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
+ if (ret != 1)
+ return -EINVAL;
+
+ mutex_lock(&devfreq_list_lock);
+ governor = find_devfreq_governor(str_governor);
+ if (IS_ERR(governor)) {
+ ret = PTR_ERR(governor);
+ goto out;
+ }
+ if (df->governor == governor)
+ goto out;
+
+ if (df->governor) {
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+ __func__, df->governor->name, ret);
+ goto out;
+ }
+ }
+ df->governor = governor;
+ strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret)
+ dev_warn(dev, "%s: Governor %s not started(%d)\n",
+ __func__, df->governor->name, ret);
+out:
+ mutex_unlock(&devfreq_list_lock);
+
+ if (!ret)
+ ret = count;
+ return ret;
+}
+static ssize_t show_available_governors(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq_governor *tmp_governor;
+ ssize_t count = 0;
+
+ mutex_lock(&devfreq_list_lock);
+ list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
+ count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+ "%s ", tmp_governor->name);
+ mutex_unlock(&devfreq_list_lock);
+
+ /* Truncate the trailing space */
+ if (count)
+ count--;
+
+ count += sprintf(&buf[count], "\n");
+
+ return count;
+}
+
static ssize_t show_freq(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ unsigned long freq;
+ struct devfreq *devfreq = to_devfreq(dev);
+
+ if (devfreq->profile->get_cur_freq &&
+ !devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
+ return sprintf(buf, "%lu\n", freq);
+
+ return sprintf(buf, "%lu\n", devfreq->previous_freq);
+}
+
+static ssize_t show_target_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
}
@@ -486,39 +790,19 @@ static ssize_t store_polling_interval(struct device *dev,
unsigned int value;
int ret;
+ if (!df->governor)
+ return -EINVAL;
+
ret = sscanf(buf, "%u", &value);
if (ret != 1)
- goto out;
-
- mutex_lock(&df->lock);
- df->profile->polling_ms = value;
- df->next_polling = df->polling_jiffies
- = msecs_to_jiffies(value);
- mutex_unlock(&df->lock);
+ return -EINVAL;
+ df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
ret = count;
- if (df->governor->no_central_polling)
- goto out;
-
- mutex_lock(&devfreq_list_lock);
- if (df->next_polling > 0 && !polling) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work,
- df->next_polling);
- }
- mutex_unlock(&devfreq_list_lock);
-out:
return ret;
}
-static ssize_t show_central_polling(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n",
- !to_devfreq(dev)->governor->no_central_polling);
-}
-
static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -529,7 +813,7 @@ static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
- goto out;
+ return -EINVAL;
mutex_lock(&df->lock);
max = df->max_freq;
@@ -543,7 +827,6 @@ static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
ret = count;
unlock:
mutex_unlock(&df->lock);
-out:
return ret;
}
@@ -563,7 +846,7 @@ static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
- goto out;
+ return -EINVAL;
mutex_lock(&df->lock);
min = df->min_freq;
@@ -577,7 +860,6 @@ static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
ret = count;
unlock:
mutex_unlock(&df->lock);
-out:
return ret;
}
@@ -587,34 +869,92 @@ static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
}
+static ssize_t show_available_freqs(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *df = to_devfreq(d);
+ struct device *dev = df->dev.parent;
+ struct opp *opp;
+ ssize_t count = 0;
+ unsigned long freq = 0;
+
+ rcu_read_lock();
+ do {
+ opp = opp_find_freq_ceil(dev, &freq);
+ if (IS_ERR(opp))
+ break;
+
+ count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+ "%lu ", freq);
+ freq++;
+ } while (1);
+ rcu_read_unlock();
+
+ /* Truncate the trailing space */
+ if (count)
+ count--;
+
+ count += sprintf(&buf[count], "\n");
+
+ return count;
+}
+
+static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *devfreq = to_devfreq(dev);
+ ssize_t len;
+ int i, j, err;
+ unsigned int max_state = devfreq->profile->max_state;
+
+ err = devfreq_update_status(devfreq, devfreq->previous_freq);
+ if (err)
+ return 0;
+
+ len = sprintf(buf, " From : To\n");
+ len += sprintf(buf + len, " :");
+ for (i = 0; i < max_state; i++)
+ len += sprintf(buf + len, "%8u",
+ devfreq->profile->freq_table[i]);
+
+ len += sprintf(buf + len, " time(ms)\n");
+
+ for (i = 0; i < max_state; i++) {
+ if (devfreq->profile->freq_table[i]
+ == devfreq->previous_freq) {
+ len += sprintf(buf + len, "*");
+ } else {
+ len += sprintf(buf + len, " ");
+ }
+ len += sprintf(buf + len, "%8u:",
+ devfreq->profile->freq_table[i]);
+ for (j = 0; j < max_state; j++)
+ len += sprintf(buf + len, "%8u",
+ devfreq->trans_table[(i * max_state) + j]);
+ len += sprintf(buf + len, "%10u\n",
+ jiffies_to_msecs(devfreq->time_in_state[i]));
+ }
+
+ len += sprintf(buf + len, "Total transition : %u\n",
+ devfreq->total_trans);
+ return len;
+}
+
static struct device_attribute devfreq_attrs[] = {
- __ATTR(governor, S_IRUGO, show_governor, NULL),
+ __ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
+ __ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
- __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+ __ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
+ __ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
store_polling_interval),
__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
+ __ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
{ },
};
-/**
- * devfreq_start_polling() - Initialize data structure for devfreq framework and
- * start polling registered devfreq devices.
- */
-static int __init devfreq_start_polling(void)
-{
- mutex_lock(&devfreq_list_lock);
- polling = false;
- devfreq_wq = create_freezable_workqueue("devfreq_wq");
- INIT_DEFERRABLE_WORK(&devfreq_work, devfreq_monitor);
- mutex_unlock(&devfreq_list_lock);
-
- devfreq_monitor(&devfreq_work.work);
- return 0;
-}
-late_initcall(devfreq_start_polling);
-
static int __init devfreq_init(void)
{
devfreq_class = class_create(THIS_MODULE, "devfreq");
@@ -622,7 +962,15 @@ static int __init devfreq_init(void)
pr_err("%s: couldn't create class\n", __FILE__);
return PTR_ERR(devfreq_class);
}
+
+ devfreq_wq = create_freezable_workqueue("devfreq_wq");
+ if (IS_ERR(devfreq_wq)) {
+ class_destroy(devfreq_class);
+ pr_err("%s: couldn't create workqueue\n", __FILE__);
+ return PTR_ERR(devfreq_wq);
+ }
devfreq_class->dev_attrs = devfreq_attrs;
+
return 0;
}
subsys_initcall(devfreq_init);
@@ -630,6 +978,7 @@ subsys_initcall(devfreq_init);
static void __exit devfreq_exit(void)
{
class_destroy(devfreq_class);
+ destroy_workqueue(devfreq_wq);
}
module_exit(devfreq_exit);
@@ -641,9 +990,9 @@ module_exit(devfreq_exit);
/**
* devfreq_recommended_opp() - Helper function to get proper OPP for the
* freq value given to target callback.
- * @dev The devfreq user device. (parent of devfreq)
- * @freq The frequency given to target function
- * @flags Flags handed from devfreq framework.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @freq: The frequency given to target function
+ * @flags: Flags handed from devfreq framework.
*
*/
struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
@@ -656,14 +1005,14 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
opp = opp_find_freq_floor(dev, freq);
/* If not available, use the closest opp */
- if (opp == ERR_PTR(-ENODEV))
+ if (opp == ERR_PTR(-ERANGE))
opp = opp_find_freq_ceil(dev, freq);
} else {
/* The freq is an lower bound. opp should be higher */
opp = opp_find_freq_ceil(dev, freq);
/* If not available, use the closest opp */
- if (opp == ERR_PTR(-ENODEV))
+ if (opp == ERR_PTR(-ERANGE))
opp = opp_find_freq_floor(dev, freq);
}
@@ -674,35 +1023,49 @@ struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
* devfreq_register_opp_notifier() - Helper function to get devfreq notified
* for any changes in the OPP availability
* changes
- * @dev The devfreq user device. (parent of devfreq)
- * @devfreq The devfreq object.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @devfreq: The devfreq object.
*/
int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
{
- struct srcu_notifier_head *nh = opp_get_notifier(dev);
+ struct srcu_notifier_head *nh;
+ int ret = 0;
+ rcu_read_lock();
+ nh = opp_get_notifier(dev);
if (IS_ERR(nh))
- return PTR_ERR(nh);
- return srcu_notifier_chain_register(nh, &devfreq->nb);
+ ret = PTR_ERR(nh);
+ rcu_read_unlock();
+ if (!ret)
+ ret = srcu_notifier_chain_register(nh, &devfreq->nb);
+
+ return ret;
}
/**
* devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
* notified for any changes in the OPP
* availability changes anymore.
- * @dev The devfreq user device. (parent of devfreq)
- * @devfreq The devfreq object.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @devfreq: The devfreq object.
*
* At exit() callback of devfreq_dev_profile, this must be included if
* devfreq_recommended_opp is used.
*/
int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
{
- struct srcu_notifier_head *nh = opp_get_notifier(dev);
+ struct srcu_notifier_head *nh;
+ int ret = 0;
+ rcu_read_lock();
+ nh = opp_get_notifier(dev);
if (IS_ERR(nh))
- return PTR_ERR(nh);
- return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+ ret = PTR_ERR(nh);
+ rcu_read_unlock();
+ if (!ret)
+ ret = srcu_notifier_chain_unregister(nh, &devfreq->nb);
+
+ return ret;
}
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 88ddc77a9bb1..741837208716 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -987,7 +987,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int err = 0;
- data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
if (data == NULL) {
dev_err(dev, "Cannot allocate memory.\n");
return -ENOMEM;
@@ -1012,31 +1012,26 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
err = -EINVAL;
}
if (err)
- goto err_regulator;
+ return err;
- data->vdd_int = regulator_get(dev, "vdd_int");
+ data->vdd_int = devm_regulator_get(dev, "vdd_int");
if (IS_ERR(data->vdd_int)) {
dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
- err = PTR_ERR(data->vdd_int);
- goto err_regulator;
+ return PTR_ERR(data->vdd_int);
}
if (data->type == TYPE_BUSF_EXYNOS4x12) {
- data->vdd_mif = regulator_get(dev, "vdd_mif");
+ data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
if (IS_ERR(data->vdd_mif)) {
dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
- err = PTR_ERR(data->vdd_mif);
- regulator_put(data->vdd_int);
- goto err_regulator;
-
+ return PTR_ERR(data->vdd_mif);
}
}
opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
if (IS_ERR(opp)) {
dev_err(dev, "Invalid initial frequency %lu kHz.\n",
- exynos4_devfreq_profile.initial_freq);
- err = PTR_ERR(opp);
- goto err_opp_add;
+ exynos4_devfreq_profile.initial_freq);
+ return PTR_ERR(opp);
}
data->curr_opp = opp;
@@ -1045,30 +1040,20 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
busfreq_mon_reset(data);
data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
- &devfreq_simple_ondemand, NULL);
- if (IS_ERR(data->devfreq)) {
- err = PTR_ERR(data->devfreq);
- goto err_opp_add;
- }
+ "simple_ondemand", NULL);
+ if (IS_ERR(data->devfreq))
+ return PTR_ERR(data->devfreq);
devfreq_register_opp_notifier(dev, data->devfreq);
err = register_pm_notifier(&data->pm_notifier);
if (err) {
dev_err(dev, "Failed to setup pm notifier\n");
- goto err_devfreq_add;
+ devfreq_remove_device(data->devfreq);
+ return err;
}
return 0;
-err_devfreq_add:
- devfreq_remove_device(data->devfreq);
-err_opp_add:
- if (data->vdd_mif)
- regulator_put(data->vdd_mif);
- regulator_put(data->vdd_int);
-err_regulator:
- kfree(data);
- return err;
}
static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
@@ -1077,10 +1062,6 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
unregister_pm_notifier(&data->pm_notifier);
devfreq_remove_device(data->devfreq);
- regulator_put(data->vdd_int);
- if (data->vdd_mif)
- regulator_put(data->vdd_mif);
- kfree(data);
return 0;
}
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index ea7f13c58ded..fad7d6321978 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -18,7 +18,24 @@
#define to_devfreq(DEV) container_of((DEV), struct devfreq, dev)
+/* Devfreq events */
+#define DEVFREQ_GOV_START 0x1
+#define DEVFREQ_GOV_STOP 0x2
+#define DEVFREQ_GOV_INTERVAL 0x3
+#define DEVFREQ_GOV_SUSPEND 0x4
+#define DEVFREQ_GOV_RESUME 0x5
+
/* Caution: devfreq->lock must be locked before calling update_devfreq */
extern int update_devfreq(struct devfreq *devfreq);
+extern void devfreq_monitor_start(struct devfreq *devfreq);
+extern void devfreq_monitor_stop(struct devfreq *devfreq);
+extern void devfreq_monitor_suspend(struct devfreq *devfreq);
+extern void devfreq_monitor_resume(struct devfreq *devfreq);
+extern void devfreq_interval_update(struct devfreq *devfreq,
+ unsigned int *delay);
+
+extern int devfreq_add_governor(struct devfreq_governor *governor);
+extern int devfreq_remove_governor(struct devfreq_governor *governor);
+
#endif /* _GOVERNOR_H */
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index af75ddd4f158..c72f942f30a8 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include <linux/module.h>
#include "governor.h"
static int devfreq_performance_func(struct devfreq *df,
@@ -26,14 +27,41 @@ static int devfreq_performance_func(struct devfreq *df,
return 0;
}
-static int performance_init(struct devfreq *devfreq)
+static int devfreq_performance_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
{
- return update_devfreq(devfreq);
+ int ret = 0;
+
+ if (event == DEVFREQ_GOV_START) {
+ mutex_lock(&devfreq->lock);
+ ret = update_devfreq(devfreq);
+ mutex_unlock(&devfreq->lock);
+ }
+
+ return ret;
}
-const struct devfreq_governor devfreq_performance = {
+static struct devfreq_governor devfreq_performance = {
.name = "performance",
- .init = performance_init,
.get_target_freq = devfreq_performance_func,
- .no_central_polling = true,
+ .event_handler = devfreq_performance_handler,
};
+
+static int __init devfreq_performance_init(void)
+{
+ return devfreq_add_governor(&devfreq_performance);
+}
+subsys_initcall(devfreq_performance_init);
+
+static void __exit devfreq_performance_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_performance);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_performance_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index fec0cdbd2477..0c6bed567e6d 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include <linux/module.h>
#include "governor.h"
static int devfreq_powersave_func(struct devfreq *df,
@@ -23,14 +24,41 @@ static int devfreq_powersave_func(struct devfreq *df,
return 0;
}
-static int powersave_init(struct devfreq *devfreq)
+static int devfreq_powersave_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
{
- return update_devfreq(devfreq);
+ int ret = 0;
+
+ if (event == DEVFREQ_GOV_START) {
+ mutex_lock(&devfreq->lock);
+ ret = update_devfreq(devfreq);
+ mutex_unlock(&devfreq->lock);
+ }
+
+ return ret;
}
-const struct devfreq_governor devfreq_powersave = {
+static struct devfreq_governor devfreq_powersave = {
.name = "powersave",
- .init = powersave_init,
.get_target_freq = devfreq_powersave_func,
- .no_central_polling = true,
+ .event_handler = devfreq_powersave_handler,
};
+
+static int __init devfreq_powersave_init(void)
+{
+ return devfreq_add_governor(&devfreq_powersave);
+}
+subsys_initcall(devfreq_powersave_init);
+
+static void __exit devfreq_powersave_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_powersave);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_powersave_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index a2e3eae79011..0720ba84ca92 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -10,8 +10,10 @@
*/
#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/math64.h>
+#include "governor.h"
/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
#define DFSO_UPTHRESHOLD (90)
@@ -88,7 +90,58 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
return 0;
}
-const struct devfreq_governor devfreq_simple_ondemand = {
+static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
+{
+ switch (event) {
+ case DEVFREQ_GOV_START:
+ devfreq_monitor_start(devfreq);
+ break;
+
+ case DEVFREQ_GOV_STOP:
+ devfreq_monitor_stop(devfreq);
+ break;
+
+ case DEVFREQ_GOV_INTERVAL:
+ devfreq_interval_update(devfreq, (unsigned int *)data);
+ break;
+
+ case DEVFREQ_GOV_SUSPEND:
+ devfreq_monitor_suspend(devfreq);
+ break;
+
+ case DEVFREQ_GOV_RESUME:
+ devfreq_monitor_resume(devfreq);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct devfreq_governor devfreq_simple_ondemand = {
.name = "simple_ondemand",
.get_target_freq = devfreq_simple_ondemand_func,
+ .event_handler = devfreq_simple_ondemand_handler,
};
+
+static int __init devfreq_simple_ondemand_init(void)
+{
+ return devfreq_add_governor(&devfreq_simple_ondemand);
+}
+subsys_initcall(devfreq_simple_ondemand_init);
+
+static void __exit devfreq_simple_ondemand_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_simple_ondemand);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_simple_ondemand_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 0681246fc89d..35de6e83c1fe 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -14,6 +14,7 @@
#include <linux/devfreq.h>
#include <linux/pm.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include "governor.h"
struct userspace_data {
@@ -116,10 +117,46 @@ static void userspace_exit(struct devfreq *devfreq)
devfreq->data = NULL;
}
-const struct devfreq_governor devfreq_userspace = {
+static int devfreq_userspace_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
+{
+ int ret = 0;
+
+ switch (event) {
+ case DEVFREQ_GOV_START:
+ ret = userspace_init(devfreq);
+ break;
+ case DEVFREQ_GOV_STOP:
+ userspace_exit(devfreq);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static struct devfreq_governor devfreq_userspace = {
.name = "userspace",
.get_target_freq = devfreq_userspace_func,
- .init = userspace_init,
- .exit = userspace_exit,
- .no_central_polling = true,
+ .event_handler = devfreq_userspace_handler,
};
+
+static int __init devfreq_userspace_init(void)
+{
+ return devfreq_add_governor(&devfreq_userspace);
+}
+subsys_initcall(devfreq_userspace_init);
+
+static void __exit devfreq_userspace_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_userspace);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_userspace_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index c4b0eb3cde81..8f0b111af4de 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1462,7 +1462,7 @@ static void dw_dma_off(struct dw_dma *dw)
dw->chan[i].initialized = false;
}
-static int __devinit dw_probe(struct platform_device *pdev)
+static int dw_probe(struct platform_device *pdev)
{
struct dw_dma_platform_data *pdata;
struct resource *io;
@@ -1700,7 +1700,7 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table);
#endif
static struct platform_driver dw_driver = {
- .remove = __devexit_p(dw_remove),
+ .remove = dw_remove,
.shutdown = dw_shutdown,
.driver = {
.name = "dw_dmac",
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 05aea3ce8506..232b4583ae93 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -545,7 +545,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
INIT_LIST_HEAD(&dma->channels);
}
-static int __devinit edma_probe(struct platform_device *pdev)
+static int edma_probe(struct platform_device *pdev)
{
struct edma_cc *ecc;
int ret;
@@ -598,7 +598,7 @@ static int __devexit edma_remove(struct platform_device *pdev)
static struct platform_driver edma_driver = {
.probe = edma_probe,
- .remove = __devexit_p(edma_remove),
+ .remove = edma_remove,
.driver = {
.name = "edma-dma-engine",
.owner = THIS_MODULE,
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 094437b9d823..4fc2980556ad 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1221,7 +1221,7 @@ out_unwind:
/* OpenFirmware Subsystem */
/*----------------------------------------------------------------------------*/
-static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+static int fsl_dma_chan_probe(struct fsldma_device *fdev,
struct device_node *node, u32 feature, const char *compatible)
{
struct fsldma_chan *chan;
@@ -1324,7 +1324,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan)
kfree(chan);
}
-static int __devinit fsldma_of_probe(struct platform_device *op)
+static int fsldma_of_probe(struct platform_device *op)
{
struct fsldma_device *fdev;
struct device_node *child;
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 02b21d7d38e5..bc764afacd9b 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -1225,7 +1225,7 @@ static void middma_shutdown(struct pci_dev *pdev)
* Initialize the PCI device, map BARs, query driver data.
* Call setup_dma to complete contoller and chan initilzation
*/
-static int __devinit intel_mid_dma_probe(struct pci_dev *pdev,
+static int intel_mid_dma_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct middma_device *device;
@@ -1432,7 +1432,7 @@ static struct pci_driver intel_mid_dma_pci_driver = {
.name = "Intel MID DMA",
.id_table = intel_mid_dma_ids,
.probe = intel_mid_dma_probe,
- .remove = __devexit_p(intel_mid_dma_remove),
+ .remove = intel_mid_dma_remove,
#ifdef CONFIG_PM
.driver = {
.pm = &intel_mid_dma_pm,
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c
index c0573061b45d..bfa9a3536e09 100644
--- a/drivers/dma/ioat/pci.c
+++ b/drivers/dma/ioat/pci.c
@@ -125,7 +125,7 @@ static struct pci_driver ioat_pci_driver = {
.name = DRV_NAME,
.id_table = ioat_pci_tbl,
.probe = ioat_pci_probe,
- .remove = __devexit_p(ioat_remove),
+ .remove = ioat_remove,
};
static struct ioatdma_device *
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 79e3eba29702..9072e173b860 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -968,7 +968,7 @@ static void iop_adma_issue_pending(struct dma_chan *chan)
*/
#define IOP_ADMA_TEST_SIZE 2000
-static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+static int iop_adma_memcpy_self_test(struct iop_adma_device *device)
{
int i;
void *src, *dest;
@@ -1042,7 +1042,7 @@ out:
}
#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
-static int __devinit
+static int
iop_adma_xor_val_self_test(struct iop_adma_device *device)
{
int i, src_idx;
@@ -1243,7 +1243,7 @@ out:
}
#ifdef CONFIG_RAID6_PQ
-static int __devinit
+static int
iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
{
/* combined sources, software pq results, and extra hw pq results */
@@ -1429,7 +1429,7 @@ static int __devexit iop_adma_remove(struct platform_device *dev)
return 0;
}
-static int __devinit iop_adma_probe(struct platform_device *pdev)
+static int iop_adma_probe(struct platform_device *pdev)
{
struct resource *res;
int ret = 0, i;
@@ -1711,7 +1711,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
static struct platform_driver iop_adma_driver = {
.probe = iop_adma_probe,
- .remove = __devexit_p(iop_adma_remove),
+ .remove = iop_adma_remove,
.driver = {
.owner = THIS_MODULE,
.name = "iop-adma",
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index 14da1f403edf..13bdf4a7e1ec 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -720,7 +720,7 @@ static int __devexit mmp_pdma_remove(struct platform_device *op)
return 0;
}
-static int __devinit mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
+static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
int idx, int irq)
{
struct mmp_pdma_phy *phy = &pdev->phy[idx];
@@ -764,7 +764,7 @@ static struct of_device_id mmp_pdma_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
-static int __devinit mmp_pdma_probe(struct platform_device *op)
+static int mmp_pdma_probe(struct platform_device *op)
{
struct mmp_pdma_device *pdev;
const struct of_device_id *of_id;
@@ -865,7 +865,7 @@ static struct platform_driver mmp_pdma_driver = {
},
.id_table = mmp_pdma_id_table,
.probe = mmp_pdma_probe,
- .remove = __devexit_p(mmp_pdma_remove),
+ .remove = mmp_pdma_remove,
};
module_platform_driver(mmp_pdma_driver);
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index f3e8d71bcbc7..323821c0c095 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -475,7 +475,7 @@ static int __devexit mmp_tdma_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
+static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
int idx, int irq, int type)
{
struct mmp_tdma_chan *tdmac;
@@ -515,7 +515,7 @@ static struct of_device_id mmp_tdma_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
-static int __devinit mmp_tdma_probe(struct platform_device *pdev)
+static int mmp_tdma_probe(struct platform_device *pdev)
{
enum mmp_tdma_type type;
const struct of_device_id *of_id;
@@ -609,7 +609,7 @@ static struct platform_driver mmp_tdma_driver = {
},
.id_table = mmp_tdma_id_table,
.probe = mmp_tdma_probe,
- .remove = __devexit_p(mmp_tdma_remove),
+ .remove = mmp_tdma_remove,
};
module_platform_driver(mmp_tdma_driver);
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2ab0a3d0eed5..2cd024a91d40 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -641,7 +641,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
return &mdesc->desc;
}
-static int __devinit mpc_dma_probe(struct platform_device *op)
+static int mpc_dma_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct device *dev = &op->dev;
@@ -818,7 +818,7 @@ static struct of_device_id mpc_dma_match[] = {
static struct platform_driver mpc_dma_driver = {
.probe = mpc_dma_probe,
- .remove = __devexit_p(mpc_dma_remove),
+ .remove = mpc_dma_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index e362e2b80efb..d12ad00da4cb 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -901,7 +901,7 @@ static void mv_xor_issue_pending(struct dma_chan *chan)
*/
#define MV_XOR_TEST_SIZE 2000
-static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+static int mv_xor_memcpy_self_test(struct mv_xor_device *device)
{
int i;
void *src, *dest;
@@ -975,7 +975,7 @@ out:
}
#define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
-static int __devinit
+static int
mv_xor_xor_self_test(struct mv_xor_device *device)
{
int i, src_idx;
@@ -1100,7 +1100,7 @@ static int __devexit mv_xor_remove(struct platform_device *dev)
return 0;
}
-static int __devinit mv_xor_probe(struct platform_device *pdev)
+static int mv_xor_probe(struct platform_device *pdev)
{
int ret = 0;
int irq;
@@ -1262,7 +1262,7 @@ mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
static struct platform_driver mv_xor_driver = {
.probe = mv_xor_probe,
- .remove = __devexit_p(mv_xor_remove),
+ .remove = mv_xor_remove,
.driver = {
.owner = THIS_MODULE,
.name = MV_XOR_NAME,
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 987ab5cd2617..eca1c4ddf039 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -843,7 +843,7 @@ static int pch_dma_resume(struct pci_dev *pdev)
}
#endif
-static int __devinit pch_dma_probe(struct pci_dev *pdev,
+static int pch_dma_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct pch_dma *pd;
@@ -1022,7 +1022,7 @@ static struct pci_driver pch_dma_driver = {
.name = DRV_NAME,
.id_table = pch_dma_id_table,
.probe = pch_dma_probe,
- .remove = __devexit_p(pch_dma_remove),
+ .remove = pch_dma_remove,
#ifdef CONFIG_PM
.suspend = pch_dma_suspend,
.resume = pch_dma_resume,
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 665668b6f2b1..95555f37ea6d 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2851,7 +2851,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
return IRQ_NONE;
}
-static int __devinit
+static int
pl330_probe(struct amba_device *adev, const struct amba_id *id)
{
struct dma_pl330_platdata *pdat;
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index f72348d0bc41..b94afc339e7f 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4361,7 +4361,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
/**
* ppc440spe_adma_probe - probe the asynch device
*/
-static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
+static int ppc440spe_adma_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct resource res;
@@ -4914,7 +4914,7 @@ MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
static struct platform_driver ppc440spe_adma_driver = {
.probe = ppc440spe_adma_probe,
- .remove = __devexit_p(ppc440spe_adma_remove),
+ .remove = ppc440spe_adma_remove,
.driver = {
.name = "PPC440SP(E)-ADMA",
.owner = THIS_MODULE,
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index b893159c1ecb..2ad628df8223 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -826,7 +826,7 @@ static const struct sa11x0_dma_channel_desc chan_desc[] = {
CD(Ser4SSPRc, DDAR_RW),
};
-static int __devinit sa11x0_dma_init_dmadev(struct dma_device *dmadev,
+static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
struct device *dev)
{
unsigned i;
@@ -891,7 +891,7 @@ static void sa11x0_dma_free_channels(struct dma_device *dmadev)
}
}
-static int __devinit sa11x0_dma_probe(struct platform_device *pdev)
+static int sa11x0_dma_probe(struct platform_device *pdev)
{
struct sa11x0_dma_dev *d;
struct resource *res;
@@ -1072,7 +1072,7 @@ static struct platform_driver sa11x0_dma_driver = {
.pm = &sa11x0_dma_pm_ops,
},
.probe = sa11x0_dma_probe,
- .remove = __devexit_p(sa11x0_dma_remove),
+ .remove = sa11x0_dma_remove,
};
bool sa11x0_dma_filter_fn(struct dma_chan *chan, void *param)
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index f41bcc5267fd..8201bb4e0cd7 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -483,7 +483,7 @@ static struct notifier_block sh_dmae_nmi_notifier __read_mostly = {
.priority = 1,
};
-static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+static int sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
int irq, unsigned long flags)
{
const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
@@ -646,7 +646,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = {
.get_partial = sh_dmae_get_partial,
};
-static int __devinit sh_dmae_probe(struct platform_device *pdev)
+static int sh_dmae_probe(struct platform_device *pdev)
{
struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
unsigned long irqflags = IRQF_DISABLED,
@@ -926,7 +926,7 @@ static struct platform_driver sh_dmae_driver = {
.pm = &sh_dmae_pm,
.name = SH_DMAE_DRV_NAME,
},
- .remove = __devexit_p(sh_dmae_remove),
+ .remove = sh_dmae_remove,
.shutdown = sh_dmae_shutdown,
};
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index d451caace806..c3de6edb9651 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -550,7 +550,7 @@ bool sirfsoc_dma_filter_id(struct dma_chan *chan, void *chan_id)
}
EXPORT_SYMBOL(sirfsoc_dma_filter_id);
-static int __devinit sirfsoc_dma_probe(struct platform_device *op)
+static int sirfsoc_dma_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct device *dev = &op->dev;
@@ -673,7 +673,7 @@ static struct of_device_id sirfsoc_dma_match[] = {
static struct platform_driver sirfsoc_dma_driver = {
.probe = sirfsoc_dma_probe,
- .remove = __devexit_p(sirfsoc_dma_remove),
+ .remove = sirfsoc_dma_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 528c62dd4b00..efdfffa13349 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1197,7 +1197,7 @@ static const struct of_device_id tegra_dma_of_match[] __devinitconst = {
MODULE_DEVICE_TABLE(of, tegra_dma_of_match);
#endif
-static int __devinit tegra_dma_probe(struct platform_device *pdev)
+static int tegra_dma_probe(struct platform_device *pdev)
{
struct resource *res;
struct tegra_dma *tdma;
@@ -1418,7 +1418,7 @@ static struct platform_driver tegra_dmac_driver = {
.of_match_table = of_match_ptr(tegra_dma_of_match),
},
.probe = tegra_dma_probe,
- .remove = __devexit_p(tegra_dma_remove),
+ .remove = tegra_dma_remove,
};
module_platform_driver(tegra_dmac_driver);
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 4e0dff59901d..98cf51e1544c 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -667,7 +667,7 @@ static irqreturn_t td_irq(int irq, void *devid)
}
-static int __devinit td_probe(struct platform_device *pdev)
+static int td_probe(struct platform_device *pdev)
{
struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
struct timb_dma *td;
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 409b92b8d346..bb82d6be793c 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -42,10 +42,10 @@ config EDAC_LEGACY_SYSFS
config EDAC_DEBUG
bool "Debugging"
help
- This turns on debugging information for the entire EDAC
- sub-system. You can insert module with "debug_level=x", current
- there're four debug levels (x=0,1,2,3 from low to high).
- Usually you should select 'N'.
+ This turns on debugging information for the entire EDAC subsystem.
+ You do so by inserting edac_module with "edac_debug_level=x." Valid
+ levels are 0-4 (from low to high) and by default it is set to 2.
+ Usually you should select 'N' here.
config EDAC_DECODE_MCE
tristate "Decode MCEs in human-readable form (only on AMD for now)"
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index cc8e7c78a23c..f74a684269ff 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -60,8 +60,8 @@ struct scrubrate {
{ 0x00, 0UL}, /* scrubbing off */
};
-static int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
- u32 *val, const char *func)
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+ u32 *val, const char *func)
{
int err = 0;
@@ -423,7 +423,6 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
u64 *hole_offset, u64 *hole_size)
{
struct amd64_pvt *pvt = mci->pvt_info;
- u64 base;
/* only revE and later have the DRAM Hole Address Register */
if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) {
@@ -462,10 +461,8 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
* addresses in the hole so that they start at 0x100000000.
*/
- base = dhar_base(pvt);
-
- *hole_base = base;
- *hole_size = (0x1ull << 32) - base;
+ *hole_base = dhar_base(pvt);
+ *hole_size = (1ULL << 32) - *hole_base;
if (boot_cpu_data.x86 > 0xf)
*hole_offset = f10_dhar_offset(pvt);
@@ -513,15 +510,15 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
{
struct amd64_pvt *pvt = mci->pvt_info;
u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
- int ret = 0;
+ int ret;
dram_base = get_dram_base(pvt, pvt->mc_node_id);
ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
&hole_size);
if (!ret) {
- if ((sys_addr >= (1ull << 32)) &&
- (sys_addr < ((1ull << 32) + hole_size))) {
+ if ((sys_addr >= (1ULL << 32)) &&
+ (sys_addr < ((1ULL << 32) + hole_size))) {
/* use DHAR to translate SysAddr to DramAddr */
dram_addr = sys_addr - hole_offset;
@@ -712,10 +709,10 @@ static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci,
/* Map the Error address to a PAGE and PAGE OFFSET. */
static inline void error_address_to_page_and_offset(u64 error_address,
- u32 *page, u32 *offset)
+ struct err_info *err)
{
- *page = (u32) (error_address >> PAGE_SHIFT);
- *offset = ((u32) error_address) & ~PAGE_MASK;
+ err->page = (u32) (error_address >> PAGE_SHIFT);
+ err->offset = ((u32) error_address) & ~PAGE_MASK;
}
/*
@@ -1026,59 +1023,44 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
}
static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
- u16 syndrome)
+ struct err_info *err)
{
- struct mem_ctl_info *src_mci;
struct amd64_pvt *pvt = mci->pvt_info;
- int channel, csrow;
- u32 page, offset;
- error_address_to_page_and_offset(sys_addr, &page, &offset);
+ error_address_to_page_and_offset(sys_addr, err);
/*
* Find out which node the error address belongs to. This may be
* different from the node that detected the error.
*/
- src_mci = find_mc_by_sys_addr(mci, sys_addr);
- if (!src_mci) {
+ err->src_mci = find_mc_by_sys_addr(mci, sys_addr);
+ if (!err->src_mci) {
amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n",
(unsigned long)sys_addr);
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- page, offset, syndrome,
- -1, -1, -1,
- "failed to map error addr to a node",
- "");
+ err->err_code = ERR_NODE;
return;
}
/* Now map the sys_addr to a CSROW */
- csrow = sys_addr_to_csrow(src_mci, sys_addr);
- if (csrow < 0) {
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- page, offset, syndrome,
- -1, -1, -1,
- "failed to map error addr to a csrow",
- "");
+ err->csrow = sys_addr_to_csrow(err->src_mci, sys_addr);
+ if (err->csrow < 0) {
+ err->err_code = ERR_CSROW;
return;
}
/* CHIPKILL enabled */
if (pvt->nbcfg & NBCFG_CHIPKILL) {
- channel = get_channel_from_ecc_syndrome(mci, syndrome);
- if (channel < 0) {
+ err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
+ if (err->channel < 0) {
/*
* Syndrome didn't map, so we don't know which of the
* 2 DIMMs is in error. So we need to ID 'both' of them
* as suspect.
*/
- amd64_mc_warn(src_mci, "unknown syndrome 0x%04x - "
+ amd64_mc_warn(err->src_mci, "unknown syndrome 0x%04x - "
"possible error reporting race\n",
- syndrome);
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- page, offset, syndrome,
- csrow, -1, -1,
- "unknown syndrome - possible error reporting race",
- "");
+ err->syndrome);
+ err->err_code = ERR_CHANNEL;
return;
}
} else {
@@ -1090,13 +1072,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
* was obtained from email communication with someone at AMD.
* (Wish the email was placed in this comment - norsk)
*/
- channel = ((sys_addr & BIT(3)) != 0);
+ err->channel = ((sys_addr & BIT(3)) != 0);
}
-
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, 1,
- page, offset, syndrome,
- csrow, channel, -1,
- "", "");
}
static int ddr2_cs_size(unsigned i, bool dct_width)
@@ -1482,7 +1459,7 @@ static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr)
/* For a given @dram_range, check if @sys_addr falls within it. */
static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
- u64 sys_addr, int *nid, int *chan_sel)
+ u64 sys_addr, int *chan_sel)
{
int cs_found = -EINVAL;
u64 chan_addr;
@@ -1555,15 +1532,14 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel);
- if (cs_found >= 0) {
- *nid = node_id;
+ if (cs_found >= 0)
*chan_sel = channel;
- }
+
return cs_found;
}
static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
- int *node, int *chan_sel)
+ int *chan_sel)
{
int cs_found = -EINVAL;
unsigned range;
@@ -1577,8 +1553,7 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
(get_dram_limit(pvt, range) >= sys_addr)) {
cs_found = f1x_match_to_this_node(pvt, range,
- sys_addr, node,
- chan_sel);
+ sys_addr, chan_sel);
if (cs_found >= 0)
break;
}
@@ -1594,22 +1569,15 @@ static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
* (MCX_ADDR).
*/
static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
- u16 syndrome)
+ struct err_info *err)
{
struct amd64_pvt *pvt = mci->pvt_info;
- u32 page, offset;
- int nid, csrow, chan = 0;
- error_address_to_page_and_offset(sys_addr, &page, &offset);
+ error_address_to_page_and_offset(sys_addr, err);
- csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
-
- if (csrow < 0) {
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- page, offset, syndrome,
- -1, -1, -1,
- "failed to map error addr to a csrow",
- "");
+ err->csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &err->channel);
+ if (err->csrow < 0) {
+ err->err_code = ERR_CSROW;
return;
}
@@ -1619,12 +1587,7 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
* this point.
*/
if (dct_ganging_enabled(pvt))
- chan = get_channel_from_ecc_syndrome(mci, syndrome);
-
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- page, offset, syndrome,
- csrow, chan, -1,
- "", "");
+ err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
}
/*
@@ -1633,14 +1596,11 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
*/
static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
{
- int dimm, size0, size1, factor = 0;
+ int dimm, size0, size1;
u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
u32 dbam = ctrl ? pvt->dbam1 : pvt->dbam0;
if (boot_cpu_data.x86 == 0xf) {
- if (pvt->dclr0 & WIDTH_128)
- factor = 1;
-
/* K8 families < revF not supported yet */
if (pvt->ext_model < K8_REV_F)
return;
@@ -1671,8 +1631,8 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
DBAM_DIMM(dimm, dbam));
amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
- dimm * 2, size0 << factor,
- dimm * 2 + 1, size1 << factor);
+ dimm * 2, size0,
+ dimm * 2 + 1, size1);
}
}
@@ -1893,101 +1853,56 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
}
-/*
- * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
- * ADDRESS and process.
- */
-static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m)
-{
- struct amd64_pvt *pvt = mci->pvt_info;
- u64 sys_addr;
- u16 syndrome;
-
- /* Ensure that the Error Address is VALID */
- if (!(m->status & MCI_STATUS_ADDRV)) {
- amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- 0, 0, 0,
- -1, -1, -1,
- "HW has no ERROR_ADDRESS available",
- "");
- return;
- }
-
- sys_addr = get_error_address(m);
- syndrome = extract_syndrome(m->status);
-
- amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
-
- pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome);
-}
-
-/* Handle any Un-correctable Errors (UEs) */
-static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m)
+static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
+ u8 ecc_type)
{
- struct mem_ctl_info *log_mci, *src_mci = NULL;
- int csrow;
- u64 sys_addr;
- u32 page, offset;
-
- log_mci = mci;
+ enum hw_event_mc_err_type err_type;
+ const char *string;
- if (!(m->status & MCI_STATUS_ADDRV)) {
- amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
- 0, 0, 0,
- -1, -1, -1,
- "HW has no ERROR_ADDRESS available",
- "");
+ if (ecc_type == 2)
+ err_type = HW_EVENT_ERR_CORRECTED;
+ else if (ecc_type == 1)
+ err_type = HW_EVENT_ERR_UNCORRECTED;
+ else {
+ WARN(1, "Something is rotten in the state of Denmark.\n");
return;
}
- sys_addr = get_error_address(m);
- error_address_to_page_and_offset(sys_addr, &page, &offset);
-
- /*
- * Find out which node the error address belongs to. This may be
- * different from the node that detected the error.
- */
- src_mci = find_mc_by_sys_addr(mci, sys_addr);
- if (!src_mci) {
- amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n",
- (unsigned long)sys_addr);
- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
- page, offset, 0,
- -1, -1, -1,
- "ERROR ADDRESS NOT mapped to a MC",
- "");
- return;
+ switch (err->err_code) {
+ case DECODE_OK:
+ string = "";
+ break;
+ case ERR_NODE:
+ string = "Failed to map error addr to a node";
+ break;
+ case ERR_CSROW:
+ string = "Failed to map error addr to a csrow";
+ break;
+ case ERR_CHANNEL:
+ string = "unknown syndrome - possible error reporting race";
+ break;
+ default:
+ string = "WTF error";
+ break;
}
- log_mci = src_mci;
-
- csrow = sys_addr_to_csrow(log_mci, sys_addr);
- if (csrow < 0) {
- amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n",
- (unsigned long)sys_addr);
- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
- page, offset, 0,
- -1, -1, -1,
- "ERROR ADDRESS NOT mapped to CS",
- "");
- } else {
- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
- page, offset, 0,
- csrow, -1, -1,
- "", "");
- }
+ edac_mc_handle_error(err_type, mci, 1,
+ err->page, err->offset, err->syndrome,
+ err->csrow, err->channel, -1,
+ string, "");
}
static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
struct mce *m)
{
- u16 ec = EC(m->status);
- u8 xec = XEC(m->status, 0x1f);
+ struct amd64_pvt *pvt = mci->pvt_info;
u8 ecc_type = (m->status >> 45) & 0x3;
+ u8 xec = XEC(m->status, 0x1f);
+ u16 ec = EC(m->status);
+ u64 sys_addr;
+ struct err_info err;
- /* Bail early out if this was an 'observed' error */
+ /* Bail out early if this was an 'observed' error */
if (PP(ec) == NBSL_PP_OBS)
return;
@@ -1995,10 +1910,16 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
if (xec && xec != F10_NBSL_EXT_ERR_ECC)
return;
+ memset(&err, 0, sizeof(err));
+
+ sys_addr = get_error_address(m);
+
if (ecc_type == 2)
- amd64_handle_ce(mci, m);
- else if (ecc_type == 1)
- amd64_handle_ue(mci, m);
+ err.syndrome = extract_syndrome(m->status);
+
+ pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, &err);
+
+ __log_bus_error(mci, &err, ecc_type);
}
void amd64_decode_bus_error(int node_id, struct mce *m)
@@ -2166,6 +2087,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
u32 cs_mode, nr_pages;
u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
+
/*
* The math on this doesn't look right on the surface because x/2*4 can
* be simplified to x*2 but this expression makes use of the fact that
@@ -2173,13 +2095,13 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
* number of bits to shift the DBAM register to extract the proper CSROW
* field.
*/
- cs_mode = (dbam >> ((csrow_nr / 2) * 4)) & 0xF;
+ cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
- edac_dbg(0, " (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode);
- edac_dbg(0, " nr_pages/channel= %u channel-count = %d\n",
- nr_pages, pvt->channel_count);
+ edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
+ csrow_nr, dct, cs_mode);
+ edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
return nr_pages;
}
@@ -2190,15 +2112,14 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
*/
static int init_csrows(struct mem_ctl_info *mci)
{
+ struct amd64_pvt *pvt = mci->pvt_info;
struct csrow_info *csrow;
struct dimm_info *dimm;
- struct amd64_pvt *pvt = mci->pvt_info;
- u64 base, mask;
- u32 val;
- int i, j, empty = 1;
- enum mem_type mtype;
enum edac_type edac_mode;
+ enum mem_type mtype;
+ int i, j, empty = 1;
int nr_pages = 0;
+ u32 val;
amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
@@ -2208,29 +2129,35 @@ static int init_csrows(struct mem_ctl_info *mci)
pvt->mc_node_id, val,
!!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
+ /*
+ * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
+ */
for_each_chip_select(i, 0, pvt) {
- csrow = mci->csrows[i];
+ bool row_dct0 = !!csrow_enabled(i, 0, pvt);
+ bool row_dct1 = false;
+
+ if (boot_cpu_data.x86 != 0xf)
+ row_dct1 = !!csrow_enabled(i, 1, pvt);
- if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) {
- edac_dbg(1, "----CSROW %d VALID for MC node %d\n",
- i, pvt->mc_node_id);
+ if (!row_dct0 && !row_dct1)
continue;
- }
+ csrow = mci->csrows[i];
empty = 0;
- if (csrow_enabled(i, 0, pvt))
+
+ edac_dbg(1, "MC node: %d, csrow: %d\n",
+ pvt->mc_node_id, i);
+
+ if (row_dct0)
nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
- if (csrow_enabled(i, 1, pvt))
- nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
- get_cs_base_and_mask(pvt, i, 0, &base, &mask);
- /* 8 bytes of resolution */
+ /* K8 has only one DCT */
+ if (boot_cpu_data.x86 != 0xf && row_dct1)
+ nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
mtype = amd64_determine_memory_type(pvt, i);
- edac_dbg(1, " for MC node %d csrow %d:\n", pvt->mc_node_id, i);
- edac_dbg(1, " nr_pages: %u\n",
- nr_pages * pvt->channel_count);
+ edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
/*
* determine whether CHIPKILL or JUST ECC or NO ECC is operating
@@ -2247,6 +2174,7 @@ static int init_csrows(struct mem_ctl_info *mci)
dimm->edac_mode = edac_mode;
dimm->nr_pages = nr_pages;
}
+ csrow->nr_pages = nr_pages;
}
return empty;
@@ -2591,6 +2519,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
mci->pvt_info = pvt;
mci->pdev = &pvt->F2->dev;
+ mci->csbased = 1;
setup_mci_misc_attrs(mci, fam_type);
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 8d4804732bac..e864f407806c 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -33,7 +33,7 @@
* detection. The mods to Rev F required more family
* information detection.
*
- * Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ * Changes/Fixes by Borislav Petkov <bp@alien8.de>:
* - misc fixes and code cleanups
*
* This module is based on the following documents
@@ -219,7 +219,7 @@
#define DBAM1 0x180
/* Extract the DIMM 'type' on the i'th DIMM from the DBAM reg value passed */
-#define DBAM_DIMM(i, reg) ((((reg) >> (4*i))) & 0xF)
+#define DBAM_DIMM(i, reg) ((((reg) >> (4*(i)))) & 0xF)
#define DBAM_MAX_VALUE 11
@@ -267,18 +267,20 @@
#define online_spare_bad_dramcs(pvt, c) (((pvt)->online_spare >> (4 + 4 * (c))) & 0x7)
#define F10_NB_ARRAY_ADDR 0xB8
-#define F10_NB_ARRAY_DRAM_ECC BIT(31)
+#define F10_NB_ARRAY_DRAM BIT(31)
/* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline */
-#define SET_NB_ARRAY_ADDRESS(section) (((section) & 0x3) << 1)
+#define SET_NB_ARRAY_ADDR(section) (((section) & 0x3) << 1)
#define F10_NB_ARRAY_DATA 0xBC
-#define SET_NB_DRAM_INJECTION_WRITE(word, bits) \
- (BIT(((word) & 0xF) + 20) | \
- BIT(17) | bits)
-#define SET_NB_DRAM_INJECTION_READ(word, bits) \
- (BIT(((word) & 0xF) + 20) | \
- BIT(16) | bits)
+#define F10_NB_ARR_ECC_WR_REQ BIT(17)
+#define SET_NB_DRAM_INJECTION_WRITE(inj) \
+ (BIT(((inj.word) & 0xF) + 20) | \
+ F10_NB_ARR_ECC_WR_REQ | inj.bit_map)
+#define SET_NB_DRAM_INJECTION_READ(inj) \
+ (BIT(((inj.word) & 0xF) + 20) | \
+ BIT(16) | inj.bit_map)
+
#define NBCAP 0xE8
#define NBCAP_CHIPKILL BIT(4)
@@ -305,9 +307,9 @@ enum amd_families {
/* Error injection control structure */
struct error_injection {
- u32 section;
- u32 word;
- u32 bit_map;
+ u32 section;
+ u32 word;
+ u32 bit_map;
};
/* low and high part of PCI config space regs */
@@ -374,6 +376,23 @@ struct amd64_pvt {
struct error_injection injection;
};
+enum err_codes {
+ DECODE_OK = 0,
+ ERR_NODE = -1,
+ ERR_CSROW = -2,
+ ERR_CHANNEL = -3,
+};
+
+struct err_info {
+ int err_code;
+ struct mem_ctl_info *src_mci;
+ int csrow;
+ int channel;
+ u16 syndrome;
+ u32 page;
+ u32 offset;
+};
+
static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
{
u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
@@ -447,7 +466,7 @@ static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
struct low_ops {
int (*early_channel_count) (struct amd64_pvt *pvt);
void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr,
- u16 syndrome);
+ struct err_info *);
int (*dbam_to_cs) (struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
int (*read_dct_pci_cfg) (struct amd64_pvt *pvt, int offset,
u32 *val, const char *func);
@@ -459,6 +478,8 @@ struct amd64_family_type {
struct low_ops ops;
};
+int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+ u32 *val, const char *func);
int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
u32 val, const char *func);
@@ -475,3 +496,15 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
u64 *hole_offset, u64 *hole_size);
#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/* Injection helpers */
+static inline void disable_caches(void *dummy)
+{
+ write_cr0(read_cr0() | X86_CR0_CD);
+ wbinvd();
+}
+
+static inline void enable_caches(void *dummy)
+{
+ write_cr0(read_cr0() & ~X86_CR0_CD);
+}
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c
index 53d972e00dfb..8c171fa1cb9b 100644
--- a/drivers/edac/amd64_edac_inj.c
+++ b/drivers/edac/amd64_edac_inj.c
@@ -22,20 +22,19 @@ static ssize_t amd64_inject_section_store(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
- int ret = 0;
+ int ret;
ret = strict_strtoul(data, 10, &value);
- if (ret != -EINVAL) {
+ if (ret < 0)
+ return ret;
- if (value > 3) {
- amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
- return -EINVAL;
- }
-
- pvt->injection.section = (u32) value;
- return count;
+ if (value > 3) {
+ amd64_warn("%s: invalid section 0x%lx\n", __func__, value);
+ return -EINVAL;
}
- return ret;
+
+ pvt->injection.section = (u32) value;
+ return count;
}
static ssize_t amd64_inject_word_show(struct device *dev,
@@ -60,20 +59,19 @@ static ssize_t amd64_inject_word_store(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
- int ret = 0;
+ int ret;
ret = strict_strtoul(data, 10, &value);
- if (ret != -EINVAL) {
+ if (ret < 0)
+ return ret;
- if (value > 8) {
- amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
- return -EINVAL;
- }
-
- pvt->injection.word = (u32) value;
- return count;
+ if (value > 8) {
+ amd64_warn("%s: invalid word 0x%lx\n", __func__, value);
+ return -EINVAL;
}
- return ret;
+
+ pvt->injection.word = (u32) value;
+ return count;
}
static ssize_t amd64_inject_ecc_vector_show(struct device *dev,
@@ -97,21 +95,19 @@ static ssize_t amd64_inject_ecc_vector_store(struct device *dev,
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
- int ret = 0;
+ int ret;
ret = strict_strtoul(data, 16, &value);
- if (ret != -EINVAL) {
+ if (ret < 0)
+ return ret;
- if (value & 0xFFFF0000) {
- amd64_warn("%s: invalid EccVector: 0x%lx\n",
- __func__, value);
- return -EINVAL;
- }
-
- pvt->injection.bit_map = (u32) value;
- return count;
+ if (value & 0xFFFF0000) {
+ amd64_warn("%s: invalid EccVector: 0x%lx\n", __func__, value);
+ return -EINVAL;
}
- return ret;
+
+ pvt->injection.bit_map = (u32) value;
+ return count;
}
/*
@@ -126,28 +122,25 @@ static ssize_t amd64_inject_read_store(struct device *dev,
struct amd64_pvt *pvt = mci->pvt_info;
unsigned long value;
u32 section, word_bits;
- int ret = 0;
+ int ret;
ret = strict_strtoul(data, 10, &value);
- if (ret != -EINVAL) {
+ if (ret < 0)
+ return ret;
- /* Form value to choose 16-byte section of cacheline */
- section = F10_NB_ARRAY_DRAM_ECC |
- SET_NB_ARRAY_ADDRESS(pvt->injection.section);
- amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+ /* Form value to choose 16-byte section of cacheline */
+ section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
- word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
- pvt->injection.bit_map);
+ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
- /* Issue 'word' and 'bit' along with the READ request */
- amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+ word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection);
- edac_dbg(0, "section=0x%x word_bits=0x%x\n",
- section, word_bits);
+ /* Issue 'word' and 'bit' along with the READ request */
+ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
- return count;
- }
- return ret;
+ edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+ return count;
}
/*
@@ -160,30 +153,43 @@ static ssize_t amd64_inject_write_store(struct device *dev,
{
struct mem_ctl_info *mci = to_mci(dev);
struct amd64_pvt *pvt = mci->pvt_info;
+ u32 section, word_bits, tmp;
unsigned long value;
- u32 section, word_bits;
- int ret = 0;
+ int ret;
ret = strict_strtoul(data, 10, &value);
- if (ret != -EINVAL) {
+ if (ret < 0)
+ return ret;
+
+ /* Form value to choose 16-byte section of cacheline */
+ section = F10_NB_ARRAY_DRAM | SET_NB_ARRAY_ADDR(pvt->injection.section);
+
+ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
- /* Form value to choose 16-byte section of cacheline */
- section = F10_NB_ARRAY_DRAM_ECC |
- SET_NB_ARRAY_ADDRESS(pvt->injection.section);
- amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
+ word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection);
- word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
- pvt->injection.bit_map);
+ pr_notice_once("Don't forget to decrease MCE polling interval in\n"
+ "/sys/bus/machinecheck/devices/machinecheck<CPUNUM>/check_interval\n"
+ "so that you can get the error report faster.\n");
- /* Issue 'word' and 'bit' along with the READ request */
- amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+ on_each_cpu(disable_caches, NULL, 1);
- edac_dbg(0, "section=0x%x word_bits=0x%x\n",
- section, word_bits);
+ /* Issue 'word' and 'bit' along with the READ request */
+ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
- return count;
+ retry:
+ /* wait until injection happens */
+ amd64_read_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, &tmp);
+ if (tmp & F10_NB_ARR_ECC_WR_REQ) {
+ cpu_relax();
+ goto retry;
}
- return ret;
+
+ on_each_cpu(enable_caches, NULL, 1);
+
+ edac_dbg(0, "section=0x%x word_bits=0x%x\n", section, word_bits);
+
+ return count;
}
/*
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 90f0b730e9bb..281f566a5513 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -416,10 +416,18 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
dimm->cschannel = chn;
/* Increment csrow location */
- row++;
- if (row == tot_csrows) {
- row = 0;
+ if (layers[0].is_virt_csrow) {
chn++;
+ if (chn == tot_channels) {
+ chn = 0;
+ row++;
+ }
+ } else {
+ row++;
+ if (row == tot_csrows) {
+ row = 0;
+ chn++;
+ }
}
/* Increment dimm location */
@@ -966,20 +974,22 @@ static void edac_ce_error(struct mem_ctl_info *mci,
long grain)
{
unsigned long remapped_page;
+ char *msg_aux = "";
+
+ if (*msg)
+ msg_aux = " ";
if (edac_mc_get_log_ce()) {
if (other_detail && *other_detail)
edac_mc_printk(mci, KERN_WARNING,
- "%d CE %s on %s (%s %s - %s)\n",
- error_count,
- msg, label, location,
- detail, other_detail);
+ "%d CE %s%son %s (%s %s - %s)\n",
+ error_count, msg, msg_aux, label,
+ location, detail, other_detail);
else
edac_mc_printk(mci, KERN_WARNING,
- "%d CE %s on %s (%s %s)\n",
- error_count,
- msg, label, location,
- detail);
+ "%d CE %s%son %s (%s %s)\n",
+ error_count, msg, msg_aux, label,
+ location, detail);
}
edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count);
@@ -1014,27 +1024,31 @@ static void edac_ue_error(struct mem_ctl_info *mci,
const char *other_detail,
const bool enable_per_layer_report)
{
+ char *msg_aux = "";
+
+ if (*msg)
+ msg_aux = " ";
+
if (edac_mc_get_log_ue()) {
if (other_detail && *other_detail)
edac_mc_printk(mci, KERN_WARNING,
- "%d UE %s on %s (%s %s - %s)\n",
- error_count,
- msg, label, location, detail,
- other_detail);
+ "%d UE %s%son %s (%s %s - %s)\n",
+ error_count, msg, msg_aux, label,
+ location, detail, other_detail);
else
edac_mc_printk(mci, KERN_WARNING,
- "%d UE %s on %s (%s %s)\n",
- error_count,
- msg, label, location, detail);
+ "%d UE %s%son %s (%s %s)\n",
+ error_count, msg, msg_aux, label,
+ location, detail);
}
if (edac_mc_get_panic_on_ue()) {
if (other_detail && *other_detail)
- panic("UE %s on %s (%s%s - %s)\n",
- msg, label, location, detail, other_detail);
+ panic("UE %s%son %s (%s%s - %s)\n",
+ msg, msg_aux, label, location, detail, other_detail);
else
- panic("UE %s on %s (%s%s)\n",
- msg, label, location, detail);
+ panic("UE %s%son %s (%s%s)\n",
+ msg, msg_aux, label, location, detail);
}
edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count);
@@ -1093,10 +1107,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
*/
for (i = 0; i < mci->n_layers; i++) {
if (pos[i] >= (int)mci->layers[i].size) {
- if (type == HW_EVENT_ERR_CORRECTED)
- p = "CE";
- else
- p = "UE";
edac_mc_printk(mci, KERN_ERR,
"INTERNAL ERROR: %s value is out of range (%d >= %d)\n",
@@ -1128,6 +1138,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
grain = 0;
p = label;
*p = '\0';
+
for (i = 0; i < mci->tot_dimms; i++) {
struct dimm_info *dimm = mci->dimms[i];
@@ -1195,6 +1206,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
/* Fill the RAM location data */
p = location;
+
for (i = 0; i < mci->n_layers; i++) {
if (pos[i] < 0)
continue;
@@ -1207,7 +1219,6 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
*(p - 1) = '\0';
/* Report the error via the trace interface */
-
grain_bits = fls_long(grain) + 1;
trace_mc_event(type, msg, label, error_count,
mci->mc_idx, top_layer, mid_layer, low_layer,
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index ed0bc07b8503..de2df92f9c77 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -180,6 +180,9 @@ static ssize_t csrow_size_show(struct device *dev,
int i;
u32 nr_pages = 0;
+ if (csrow->mci->csbased)
+ return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
+
for (i = 0; i < csrow->nr_channels; i++)
nr_pages += csrow->channels[i]->dimm->nr_pages;
return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
@@ -373,6 +376,7 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
csrow->dev.bus = &mci->bus;
device_initialize(&csrow->dev);
csrow->dev.parent = &mci->dev;
+ csrow->mci = mci;
dev_set_name(&csrow->dev, "csrow%d", index);
dev_set_drvdata(&csrow->dev, csrow);
@@ -777,10 +781,14 @@ static ssize_t mci_size_mb_show(struct device *dev,
for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
struct csrow_info *csrow = mci->csrows[csrow_idx];
- for (j = 0; j < csrow->nr_channels; j++) {
- struct dimm_info *dimm = csrow->channels[j]->dimm;
+ if (csrow->mci->csbased) {
+ total_pages += csrow->nr_pages;
+ } else {
+ for (j = 0; j < csrow->nr_channels; j++) {
+ struct dimm_info *dimm = csrow->channels[j]->dimm;
- total_pages += dimm->nr_pages;
+ total_pages += dimm->nr_pages;
+ }
}
}
@@ -838,14 +846,8 @@ static ssize_t edac_fake_inject_write(struct file *file,
return count;
}
-static int debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static const struct file_operations debug_fake_inject_fops = {
- .open = debugfs_open,
+ .open = simple_open,
.write = edac_fake_inject_write,
.llseek = generic_file_llseek,
};
@@ -1124,10 +1126,15 @@ int __init edac_mc_sysfs_init(void)
edac_subsys = edac_get_sysfs_subsys();
if (edac_subsys == NULL) {
edac_dbg(1, "no edac_subsys\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
+ if (!mci_pdev) {
+ err = -ENOMEM;
+ goto out_put_sysfs;
+ }
mci_pdev->bus = edac_subsys;
mci_pdev->type = &mc_attr_type;
@@ -1136,11 +1143,18 @@ int __init edac_mc_sysfs_init(void)
err = device_add(mci_pdev);
if (err < 0)
- return err;
+ goto out_dev_free;
edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
return 0;
+
+ out_dev_free:
+ kfree(mci_pdev);
+ out_put_sysfs:
+ edac_put_sysfs_subsys();
+ out:
+ return err;
}
void __exit edac_mc_sysfs_exit(void)
@@ -1148,4 +1162,5 @@ void __exit edac_mc_sysfs_exit(void)
put_device(mci_pdev);
device_del(mci_pdev);
edac_put_sysfs_subsys();
+ kfree(mci_pdev);
}
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 58a28d838f37..12c951a2c33d 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -18,9 +18,29 @@
#define EDAC_VERSION "Ver: 3.0.0"
#ifdef CONFIG_EDAC_DEBUG
+
+static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
+{
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val < 0 || val > 4)
+ return -EINVAL;
+
+ return param_set_int(buf, kp);
+}
+
/* Values of 0 to 4 will generate output */
int edac_debug_level = 2;
EXPORT_SYMBOL_GPL(edac_debug_level);
+
+module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
+ &edac_debug_level, 0644);
+MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
#endif
/* scope is to module level only */
@@ -132,10 +152,3 @@ module_exit(edac_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
MODULE_DESCRIPTION("Core library routines for EDAC reporting");
-
-/* refer to *_sysfs.c files for parameters that are exported via sysfs */
-
-#ifdef CONFIG_EDAC_DEBUG
-module_param(edac_debug_level, int, 0644);
-MODULE_PARM_DESC(edac_debug_level, "Debug level");
-#endif
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index ee87ef972ead..dd370f92ace3 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -470,7 +470,8 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
pci->mod_name = mod_name;
pci->ctl_name = EDAC_PCI_GENCTL_NAME;
- pci->edac_check = edac_pci_generic_check;
+ if (edac_op_state == EDAC_OPSTATE_POLL)
+ pci->edac_check = edac_pci_generic_check;
pdata->edac_idx = edac_pci_idx++;
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index e164c555a337..dc6e905ee1a5 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -645,20 +645,16 @@ typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
/*
* pci_dev parity list iterator
- * Scan the PCI device list for one pass, looking for SERRORs
- * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ *
+ * Scan the PCI device list looking for SERRORs, Master Parity ERRORS or
+ * Parity ERRORs on primary or secondary devices.
*/
static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
{
struct pci_dev *dev = NULL;
- /* request for kernel access to the next PCI device, if any,
- * and while we are looking at it have its reference count
- * bumped until we are done with it
- */
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ for_each_pci_dev(dev)
fn(dev);
- }
}
/*
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index 6c86f6e54558..351945fa2ecd 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -5,7 +5,7 @@
*
* 2007 (c) MontaVista Software, Inc.
* 2010 (c) Advanced Micro Devices Inc.
- * Borislav Petkov <borislav.petkov@amd.com>
+ * Borislav Petkov <bp@alien8.de>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c
index c769f477fd22..7ea4cc2e8bd2 100644
--- a/drivers/edac/highbank_mc_edac.c
+++ b/drivers/edac/highbank_mc_edac.c
@@ -113,14 +113,8 @@ static ssize_t highbank_mc_err_inject_write(struct file *file,
return count;
}
-static int debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static const struct file_operations highbank_mc_debug_inject_fops = {
- .open = debugfs_open,
+ .open = simple_open,
.write = highbank_mc_err_inject_write,
.llseek = generic_file_llseek,
};
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index a09d0667f72a..9d669cd43618 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -197,8 +197,8 @@ static const char *ferr_fat_fbd_name[] = {
[0] = "Memory Write error on non-redundant retry or "
"FBD configuration Write error on retry",
};
-#define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28))
-#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+#define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3)
+#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22))
#define FERR_NF_FBD 0xa0
static const char *ferr_nf_fbd_name[] = {
@@ -225,7 +225,7 @@ static const char *ferr_nf_fbd_name[] = {
[1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
[0] = "Uncorrectable Data ECC on Replay",
};
-#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28))
+#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3)
#define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\
(1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\
(1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\
@@ -464,7 +464,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_nf_fbd_name));
specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
- branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
+ branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0;
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
REDMEMA, &syndrome);
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 3672101023bd..10c8c00d6469 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -816,7 +816,7 @@ static ssize_t i7core_inject_store_##param( \
struct device_attribute *mattr, \
const char *data, size_t count) \
{ \
- struct mem_ctl_info *mci = to_mci(dev); \
+ struct mem_ctl_info *mci = dev_get_drvdata(dev); \
struct i7core_pvt *pvt; \
long value; \
int rc; \
@@ -845,7 +845,7 @@ static ssize_t i7core_inject_show_##param( \
struct device_attribute *mattr, \
char *data) \
{ \
- struct mem_ctl_info *mci = to_mci(dev); \
+ struct mem_ctl_info *mci = dev_get_drvdata(dev); \
struct i7core_pvt *pvt; \
\
pvt = mci->pvt_info; \
@@ -1052,7 +1052,7 @@ static ssize_t i7core_show_counter_##param( \
struct device_attribute *mattr, \
char *data) \
{ \
- struct mem_ctl_info *mci = to_mci(dev); \
+ struct mem_ctl_info *mci = dev_get_drvdata(dev); \
struct i7core_pvt *pvt = mci->pvt_info; \
\
edac_dbg(1, "\n"); \
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
index 069e26c11c4f..a98020409fa9 100644
--- a/drivers/edac/i82975x_edac.c
+++ b/drivers/edac/i82975x_edac.c
@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
static void i82975x_init_csrows(struct mem_ctl_info *mci,
struct pci_dev *pdev, void __iomem *mch_window)
{
- static const char *labels[4] = {
- "DIMM A1", "DIMM A2",
- "DIMM B1", "DIMM B2"
- };
struct csrow_info *csrow;
unsigned long last_cumul_size;
u8 value;
@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
dimm = mci->csrows[index]->channels[chan]->dimm;
dimm->nr_pages = nr_pages / csrow->nr_channels;
- strncpy(csrow->channels[chan]->dimm->label,
- labels[(index >> 1) + (chan * 2)],
- EDAC_MC_LABEL_LEN);
+
+ snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d",
+ (chan == 0) ? 'A' : 'B',
+ index);
dimm->grain = 1 << 7; /* 128Byte cache-line resolution */
dimm->dtype = i82975x_dram_type(mch_window, index);
dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index d0c372e30de4..ad637572d8c7 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -64,7 +64,7 @@ EXPORT_SYMBOL_GPL(to_msgs);
const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" };
EXPORT_SYMBOL_GPL(ii_msgs);
-static const char * const f15h_ic_mce_desc[] = {
+static const char * const f15h_mc1_mce_desc[] = {
"UC during a demand linefill from L2",
"Parity error during data load from IC",
"Parity error for IC valid bit",
@@ -84,7 +84,7 @@ static const char * const f15h_ic_mce_desc[] = {
"fetch address FIFO"
};
-static const char * const f15h_cu_mce_desc[] = {
+static const char * const f15h_mc2_mce_desc[] = {
"Fill ECC error on data fills", /* xec = 0x4 */
"Fill parity error on insn fills",
"Prefetcher request FIFO parity error",
@@ -101,7 +101,7 @@ static const char * const f15h_cu_mce_desc[] = {
"PRB address parity error"
};
-static const char * const nb_mce_desc[] = {
+static const char * const mc4_mce_desc[] = {
"DRAM ECC error detected on the NB",
"CRC error detected on HT link",
"Link-defined sync error packets detected on HT link",
@@ -123,7 +123,7 @@ static const char * const nb_mce_desc[] = {
"ECC Error in the Probe Filter directory"
};
-static const char * const fr_ex_mce_desc[] = {
+static const char * const mc5_mce_desc[] = {
"CPU Watchdog timer expire",
"Wakeup array dest tag",
"AG payload array",
@@ -139,7 +139,7 @@ static const char * const fr_ex_mce_desc[] = {
"DE error occurred"
};
-static bool f12h_dc_mce(u16 ec, u8 xec)
+static bool f12h_mc0_mce(u16 ec, u8 xec)
{
bool ret = false;
@@ -157,26 +157,26 @@ static bool f12h_dc_mce(u16 ec, u8 xec)
return ret;
}
-static bool f10h_dc_mce(u16 ec, u8 xec)
+static bool f10h_mc0_mce(u16 ec, u8 xec)
{
if (R4(ec) == R4_GEN && LL(ec) == LL_L1) {
pr_cont("during data scrub.\n");
return true;
}
- return f12h_dc_mce(ec, xec);
+ return f12h_mc0_mce(ec, xec);
}
-static bool k8_dc_mce(u16 ec, u8 xec)
+static bool k8_mc0_mce(u16 ec, u8 xec)
{
if (BUS_ERROR(ec)) {
pr_cont("during system linefill.\n");
return true;
}
- return f10h_dc_mce(ec, xec);
+ return f10h_mc0_mce(ec, xec);
}
-static bool f14h_dc_mce(u16 ec, u8 xec)
+static bool f14h_mc0_mce(u16 ec, u8 xec)
{
u8 r4 = R4(ec);
bool ret = true;
@@ -228,7 +228,7 @@ static bool f14h_dc_mce(u16 ec, u8 xec)
return ret;
}
-static bool f15h_dc_mce(u16 ec, u8 xec)
+static bool f15h_mc0_mce(u16 ec, u8 xec)
{
bool ret = true;
@@ -275,12 +275,12 @@ static bool f15h_dc_mce(u16 ec, u8 xec)
return ret;
}
-static void amd_decode_dc_mce(struct mce *m)
+static void decode_mc0_mce(struct mce *m)
{
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
- pr_emerg(HW_ERR "Data Cache Error: ");
+ pr_emerg(HW_ERR "MC0 Error: ");
/* TLB error signatures are the same across families */
if (TLB_ERROR(ec)) {
@@ -290,13 +290,13 @@ static void amd_decode_dc_mce(struct mce *m)
: (xec ? "multimatch" : "parity")));
return;
}
- } else if (fam_ops->dc_mce(ec, xec))
+ } else if (fam_ops->mc0_mce(ec, xec))
;
else
- pr_emerg(HW_ERR "Corrupted DC MCE info?\n");
+ pr_emerg(HW_ERR "Corrupted MC0 MCE info?\n");
}
-static bool k8_ic_mce(u16 ec, u8 xec)
+static bool k8_mc1_mce(u16 ec, u8 xec)
{
u8 ll = LL(ec);
bool ret = true;
@@ -330,7 +330,7 @@ static bool k8_ic_mce(u16 ec, u8 xec)
return ret;
}
-static bool f14h_ic_mce(u16 ec, u8 xec)
+static bool f14h_mc1_mce(u16 ec, u8 xec)
{
u8 r4 = R4(ec);
bool ret = true;
@@ -349,7 +349,7 @@ static bool f14h_ic_mce(u16 ec, u8 xec)
return ret;
}
-static bool f15h_ic_mce(u16 ec, u8 xec)
+static bool f15h_mc1_mce(u16 ec, u8 xec)
{
bool ret = true;
@@ -358,19 +358,19 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
switch (xec) {
case 0x0 ... 0xa:
- pr_cont("%s.\n", f15h_ic_mce_desc[xec]);
+ pr_cont("%s.\n", f15h_mc1_mce_desc[xec]);
break;
case 0xd:
- pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]);
+ pr_cont("%s.\n", f15h_mc1_mce_desc[xec-2]);
break;
case 0x10:
- pr_cont("%s.\n", f15h_ic_mce_desc[xec-4]);
+ pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
break;
case 0x11 ... 0x14:
- pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]);
+ pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
break;
default:
@@ -379,12 +379,12 @@ static bool f15h_ic_mce(u16 ec, u8 xec)
return ret;
}
-static void amd_decode_ic_mce(struct mce *m)
+static void decode_mc1_mce(struct mce *m)
{
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
- pr_emerg(HW_ERR "Instruction Cache Error: ");
+ pr_emerg(HW_ERR "MC1 Error: ");
if (TLB_ERROR(ec))
pr_cont("%s TLB %s.\n", LL_MSG(ec),
@@ -393,18 +393,18 @@ static void amd_decode_ic_mce(struct mce *m)
bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
- } else if (fam_ops->ic_mce(ec, xec))
+ } else if (fam_ops->mc1_mce(ec, xec))
;
else
- pr_emerg(HW_ERR "Corrupted IC MCE info?\n");
+ pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
}
-static void amd_decode_bu_mce(struct mce *m)
+static void decode_mc2_mce(struct mce *m)
{
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
- pr_emerg(HW_ERR "Bus Unit Error");
+ pr_emerg(HW_ERR "MC2 Error");
if (xec == 0x1)
pr_cont(" in the write data buffers.\n");
@@ -429,24 +429,24 @@ static void amd_decode_bu_mce(struct mce *m)
pr_cont(": %s parity/ECC error during data "
"access from L2.\n", R4_MSG(ec));
else
- goto wrong_bu_mce;
+ goto wrong_mc2_mce;
} else
- goto wrong_bu_mce;
+ goto wrong_mc2_mce;
} else
- goto wrong_bu_mce;
+ goto wrong_mc2_mce;
return;
-wrong_bu_mce:
- pr_emerg(HW_ERR "Corrupted BU MCE info?\n");
+ wrong_mc2_mce:
+ pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
}
-static void amd_decode_cu_mce(struct mce *m)
+static void decode_f15_mc2_mce(struct mce *m)
{
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
- pr_emerg(HW_ERR "Combined Unit Error: ");
+ pr_emerg(HW_ERR "MC2 Error: ");
if (TLB_ERROR(ec)) {
if (xec == 0x0)
@@ -454,63 +454,63 @@ static void amd_decode_cu_mce(struct mce *m)
else if (xec == 0x1)
pr_cont("Poison data provided for TLB fill.\n");
else
- goto wrong_cu_mce;
+ goto wrong_f15_mc2_mce;
} else if (BUS_ERROR(ec)) {
if (xec > 2)
- goto wrong_cu_mce;
+ goto wrong_f15_mc2_mce;
pr_cont("Error during attempted NB data read.\n");
} else if (MEM_ERROR(ec)) {
switch (xec) {
case 0x4 ... 0xc:
- pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]);
+ pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x4]);
break;
case 0x10 ... 0x14:
- pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]);
+ pr_cont("%s.\n", f15h_mc2_mce_desc[xec - 0x7]);
break;
default:
- goto wrong_cu_mce;
+ goto wrong_f15_mc2_mce;
}
}
return;
-wrong_cu_mce:
- pr_emerg(HW_ERR "Corrupted CU MCE info?\n");
+ wrong_f15_mc2_mce:
+ pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n");
}
-static void amd_decode_ls_mce(struct mce *m)
+static void decode_mc3_mce(struct mce *m)
{
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask);
if (boot_cpu_data.x86 >= 0x14) {
- pr_emerg("You shouldn't be seeing an LS MCE on this cpu family,"
+ pr_emerg("You shouldn't be seeing MC3 MCE on this cpu family,"
" please report on LKML.\n");
return;
}
- pr_emerg(HW_ERR "Load Store Error");
+ pr_emerg(HW_ERR "MC3 Error");
if (xec == 0x0) {
u8 r4 = R4(ec);
if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR))
- goto wrong_ls_mce;
+ goto wrong_mc3_mce;
pr_cont(" during %s.\n", R4_MSG(ec));
} else
- goto wrong_ls_mce;
+ goto wrong_mc3_mce;
return;
-wrong_ls_mce:
- pr_emerg(HW_ERR "Corrupted LS MCE info?\n");
+ wrong_mc3_mce:
+ pr_emerg(HW_ERR "Corrupted MC3 MCE info?\n");
}
-void amd_decode_nb_mce(struct mce *m)
+static void decode_mc4_mce(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
int node_id = amd_get_nb_id(m->extcpu);
@@ -518,7 +518,7 @@ void amd_decode_nb_mce(struct mce *m)
u8 xec = XEC(m->status, 0x1f);
u8 offset = 0;
- pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id);
+ pr_emerg(HW_ERR "MC4 Error (node %d): ", node_id);
switch (xec) {
case 0x0 ... 0xe:
@@ -527,9 +527,9 @@ void amd_decode_nb_mce(struct mce *m)
if (xec == 0x0 || xec == 0x8) {
/* no ECCs on F11h */
if (c->x86 == 0x11)
- goto wrong_nb_mce;
+ goto wrong_mc4_mce;
- pr_cont("%s.\n", nb_mce_desc[xec]);
+ pr_cont("%s.\n", mc4_mce_desc[xec]);
if (nb_bus_decoder)
nb_bus_decoder(node_id, m);
@@ -543,14 +543,14 @@ void amd_decode_nb_mce(struct mce *m)
else if (BUS_ERROR(ec))
pr_cont("DMA Exclusion Vector Table Walk error.\n");
else
- goto wrong_nb_mce;
+ goto wrong_mc4_mce;
return;
case 0x19:
if (boot_cpu_data.x86 == 0x15)
pr_cont("Compute Unit Data Error.\n");
else
- goto wrong_nb_mce;
+ goto wrong_mc4_mce;
return;
case 0x1c ... 0x1f:
@@ -558,46 +558,44 @@ void amd_decode_nb_mce(struct mce *m)
break;
default:
- goto wrong_nb_mce;
+ goto wrong_mc4_mce;
}
- pr_cont("%s.\n", nb_mce_desc[xec - offset]);
+ pr_cont("%s.\n", mc4_mce_desc[xec - offset]);
return;
-wrong_nb_mce:
- pr_emerg(HW_ERR "Corrupted NB MCE info?\n");
+ wrong_mc4_mce:
+ pr_emerg(HW_ERR "Corrupted MC4 MCE info?\n");
}
-EXPORT_SYMBOL_GPL(amd_decode_nb_mce);
-static void amd_decode_fr_mce(struct mce *m)
+static void decode_mc5_mce(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
u8 xec = XEC(m->status, xec_mask);
if (c->x86 == 0xf || c->x86 == 0x11)
- goto wrong_fr_mce;
+ goto wrong_mc5_mce;
- pr_emerg(HW_ERR "%s Error: ",
- (c->x86 == 0x15 ? "Execution Unit" : "FIROB"));
+ pr_emerg(HW_ERR "MC5 Error: ");
if (xec == 0x0 || xec == 0xc)
- pr_cont("%s.\n", fr_ex_mce_desc[xec]);
+ pr_cont("%s.\n", mc5_mce_desc[xec]);
else if (xec < 0xd)
- pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]);
+ pr_cont("%s parity error.\n", mc5_mce_desc[xec]);
else
- goto wrong_fr_mce;
+ goto wrong_mc5_mce;
return;
-wrong_fr_mce:
- pr_emerg(HW_ERR "Corrupted FR MCE info?\n");
+ wrong_mc5_mce:
+ pr_emerg(HW_ERR "Corrupted MC5 MCE info?\n");
}
-static void amd_decode_fp_mce(struct mce *m)
+static void decode_mc6_mce(struct mce *m)
{
u8 xec = XEC(m->status, xec_mask);
- pr_emerg(HW_ERR "Floating Point Unit Error: ");
+ pr_emerg(HW_ERR "MC6 Error: ");
switch (xec) {
case 0x1:
@@ -621,7 +619,7 @@ static void amd_decode_fp_mce(struct mce *m)
break;
default:
- goto wrong_fp_mce;
+ goto wrong_mc6_mce;
break;
}
@@ -629,8 +627,8 @@ static void amd_decode_fp_mce(struct mce *m)
return;
-wrong_fp_mce:
- pr_emerg(HW_ERR "Corrupted FP MCE info?\n");
+ wrong_mc6_mce:
+ pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
}
static inline void amd_decode_err_code(u16 ec)
@@ -669,74 +667,94 @@ static bool amd_filter_mce(struct mce *m)
return false;
}
+static const char *decode_error_status(struct mce *m)
+{
+ if (m->status & MCI_STATUS_UC) {
+ if (m->status & MCI_STATUS_PCC)
+ return "System Fatal error.";
+ if (m->mcgstatus & MCG_STATUS_RIPV)
+ return "Uncorrected, software restartable error.";
+ return "Uncorrected, software containable error.";
+ }
+
+ if (m->status & MCI_STATUS_DEFERRED)
+ return "Deferred error.";
+
+ return "Corrected error, no action required.";
+}
+
int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
{
struct mce *m = (struct mce *)data;
- struct cpuinfo_x86 *c = &boot_cpu_data;
+ struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
int ecc;
if (amd_filter_mce(m))
return NOTIFY_STOP;
- pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s",
- m->extcpu, m->bank,
- ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
- ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
- ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
- ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
- ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
-
- if (c->x86 == 0x15)
- pr_cont("|%s|%s",
- ((m->status & BIT_64(44)) ? "Deferred" : "-"),
- ((m->status & BIT_64(43)) ? "Poison" : "-"));
-
- /* do the two bits[14:13] together */
- ecc = (m->status >> 45) & 0x3;
- if (ecc)
- pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
-
- pr_cont("]: 0x%016llx\n", m->status);
-
- if (m->status & MCI_STATUS_ADDRV)
- pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
-
switch (m->bank) {
case 0:
- amd_decode_dc_mce(m);
+ decode_mc0_mce(m);
break;
case 1:
- amd_decode_ic_mce(m);
+ decode_mc1_mce(m);
break;
case 2:
if (c->x86 == 0x15)
- amd_decode_cu_mce(m);
+ decode_f15_mc2_mce(m);
else
- amd_decode_bu_mce(m);
+ decode_mc2_mce(m);
break;
case 3:
- amd_decode_ls_mce(m);
+ decode_mc3_mce(m);
break;
case 4:
- amd_decode_nb_mce(m);
+ decode_mc4_mce(m);
break;
case 5:
- amd_decode_fr_mce(m);
+ decode_mc5_mce(m);
break;
case 6:
- amd_decode_fp_mce(m);
+ decode_mc6_mce(m);
break;
default:
break;
}
+ pr_emerg(HW_ERR "Error Status: %s\n", decode_error_status(m));
+
+ pr_emerg(HW_ERR "CPU:%d (%x:%x:%x) MC%d_STATUS[%s|%s|%s|%s|%s",
+ m->extcpu,
+ c->x86, c->x86_model, c->x86_mask,
+ m->bank,
+ ((m->status & MCI_STATUS_OVER) ? "Over" : "-"),
+ ((m->status & MCI_STATUS_UC) ? "UE" : "CE"),
+ ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"),
+ ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"),
+ ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
+
+ if (c->x86 == 0x15)
+ pr_cont("|%s|%s",
+ ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
+ ((m->status & MCI_STATUS_POISON) ? "Poison" : "-"));
+
+ /* do the two bits[14:13] together */
+ ecc = (m->status >> 45) & 0x3;
+ if (ecc)
+ pr_cont("|%sECC", ((ecc == 2) ? "C" : "U"));
+
+ pr_cont("]: 0x%016llx\n", m->status);
+
+ if (m->status & MCI_STATUS_ADDRV)
+ pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
+
amd_decode_err_code(m->status & 0xffff);
return NOTIFY_STOP;
@@ -763,35 +781,35 @@ static int __init mce_amd_init(void)
switch (c->x86) {
case 0xf:
- fam_ops->dc_mce = k8_dc_mce;
- fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->mc0_mce = k8_mc0_mce;
+ fam_ops->mc1_mce = k8_mc1_mce;
break;
case 0x10:
- fam_ops->dc_mce = f10h_dc_mce;
- fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->mc0_mce = f10h_mc0_mce;
+ fam_ops->mc1_mce = k8_mc1_mce;
break;
case 0x11:
- fam_ops->dc_mce = k8_dc_mce;
- fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->mc0_mce = k8_mc0_mce;
+ fam_ops->mc1_mce = k8_mc1_mce;
break;
case 0x12:
- fam_ops->dc_mce = f12h_dc_mce;
- fam_ops->ic_mce = k8_ic_mce;
+ fam_ops->mc0_mce = f12h_mc0_mce;
+ fam_ops->mc1_mce = k8_mc1_mce;
break;
case 0x14:
nb_err_cpumask = 0x3;
- fam_ops->dc_mce = f14h_dc_mce;
- fam_ops->ic_mce = f14h_ic_mce;
+ fam_ops->mc0_mce = f14h_mc0_mce;
+ fam_ops->mc1_mce = f14h_mc1_mce;
break;
case 0x15:
xec_mask = 0x1f;
- fam_ops->dc_mce = f15h_dc_mce;
- fam_ops->ic_mce = f15h_ic_mce;
+ fam_ops->mc0_mce = f15h_mc0_mce;
+ fam_ops->mc1_mce = f15h_mc1_mce;
break;
default:
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 8c87a5e87057..679679951e23 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -29,10 +29,8 @@
#define R4(x) (((x) >> 4) & 0xf)
#define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!")
-/*
- * F3x4C bits (MCi_STATUS' high half)
- */
-#define NBSH_ERR_CPU_VAL BIT(24)
+#define MCI_STATUS_DEFERRED BIT_64(44)
+#define MCI_STATUS_POISON BIT_64(43)
enum tt_ids {
TT_INSTR = 0,
@@ -78,14 +76,13 @@ extern const char * const ii_msgs[];
* per-family decoder ops
*/
struct amd_decoder_ops {
- bool (*dc_mce)(u16, u8);
- bool (*ic_mce)(u16, u8);
+ bool (*mc0_mce)(u16, u8);
+ bool (*mc1_mce)(u16, u8);
};
void amd_report_gart_errors(bool);
void amd_register_ecc_decoder(void (*f)(int, struct mce *));
void amd_unregister_ecc_decoder(void (*f)(int, struct mce *));
-void amd_decode_nb_mce(struct mce *);
int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data);
#endif /* _EDAC_MCE_AMD_H */
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 66b5151c1080..2ae78f20cc28 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -6,7 +6,7 @@
* This file may be distributed under the terms of the GNU General Public
* License version 2.
*
- * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com>
+ * Copyright (c) 2010: Borislav Petkov <bp@alien8.de>
* Advanced Micro Devices Inc.
*/
@@ -168,6 +168,6 @@ module_init(edac_init_mce_inject);
module_exit(edac_exit_mce_inject);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
MODULE_AUTHOR("AMD Inc.");
MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index e87196f6d2d2..eda2a1aa4adb 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -91,7 +91,7 @@ static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
return IRQ_HANDLED;
}
-static int __devinit adc_jack_probe(struct platform_device *pdev)
+static int adc_jack_probe(struct platform_device *pdev)
{
struct adc_jack_data *data;
struct adc_jack_pdata *pdata = pdev->dev.platform_data;
@@ -175,7 +175,7 @@ out:
return err;
}
-static int __devexit adc_jack_remove(struct platform_device *pdev)
+static int adc_jack_remove(struct platform_device *pdev)
{
struct adc_jack_data *data = platform_get_drvdata(pdev);
@@ -188,7 +188,7 @@ static int __devexit adc_jack_remove(struct platform_device *pdev)
static struct platform_driver adc_jack_driver = {
.probe = adc_jack_probe,
- .remove = __devexit_p(adc_jack_remove),
+ .remove = adc_jack_remove,
.driver = {
.name = "adc-jack",
.owner = THIS_MODULE,
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index cdab9e598297..f10f05d4ee9c 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -337,7 +337,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
return IRQ_HANDLED;
}
-static int __devinit arizona_extcon_probe(struct platform_device *pdev)
+static int arizona_extcon_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata;
@@ -517,7 +517,7 @@ err:
return ret;
}
-static int __devexit arizona_extcon_remove(struct platform_device *pdev)
+static int arizona_extcon_remove(struct platform_device *pdev)
{
struct arizona_extcon_info *info = platform_get_drvdata(pdev);
struct arizona *arizona = info->arizona;
@@ -544,7 +544,7 @@ static struct platform_driver arizona_extcon_driver = {
.owner = THIS_MODULE,
},
.probe = arizona_extcon_probe,
- .remove = __devexit_p(arizona_extcon_remove),
+ .remove = arizona_extcon_remove,
};
module_platform_driver(arizona_extcon_driver);
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 71d3ab7b3d8d..1b14bfcdc176 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -76,7 +76,7 @@ static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
return -EINVAL;
}
-static int __devinit gpio_extcon_probe(struct platform_device *pdev)
+static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
struct gpio_extcon_data *extcon_data;
@@ -137,7 +137,7 @@ err:
return ret;
}
-static int __devexit gpio_extcon_remove(struct platform_device *pdev)
+static int gpio_extcon_remove(struct platform_device *pdev)
{
struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
@@ -150,7 +150,7 @@ static int __devexit gpio_extcon_remove(struct platform_device *pdev)
static struct platform_driver gpio_extcon_driver = {
.probe = gpio_extcon_probe,
- .remove = __devexit_p(gpio_extcon_remove),
+ .remove = gpio_extcon_remove,
.driver = {
.name = "extcon-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index a17d0d91ada2..b656dfa401a6 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -648,7 +648,7 @@ out:
return ret;
}
-static int __devinit max77693_muic_probe(struct platform_device *pdev)
+static int max77693_muic_probe(struct platform_device *pdev)
{
struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
@@ -774,7 +774,7 @@ err_kfree:
return ret;
}
-static int __devexit max77693_muic_remove(struct platform_device *pdev)
+static int max77693_muic_remove(struct platform_device *pdev)
{
struct max77693_muic_info *info = platform_get_drvdata(pdev);
int i;
@@ -795,7 +795,7 @@ static struct platform_driver max77693_muic_driver = {
.owner = THIS_MODULE,
},
.probe = max77693_muic_probe,
- .remove = __devexit_p(max77693_muic_remove),
+ .remove = max77693_muic_remove,
};
module_platform_driver(max77693_muic_driver);
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 77b66b0cc8f5..bad76f51161b 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -426,7 +426,7 @@ static void max8997_muic_detect_dev(struct max8997_muic_info *info)
max8997_muic_handle_charger_type(info, chg_type);
}
-static int __devinit max8997_muic_probe(struct platform_device *pdev)
+static int max8997_muic_probe(struct platform_device *pdev)
{
struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
@@ -508,7 +508,7 @@ err_kfree:
return ret;
}
-static int __devexit max8997_muic_remove(struct platform_device *pdev)
+static int max8997_muic_remove(struct platform_device *pdev)
{
struct max8997_muic_info *info = platform_get_drvdata(pdev);
int i;
@@ -531,7 +531,7 @@ static struct platform_driver max8997_muic_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_muic_probe,
- .remove = __devexit_p(max8997_muic_remove),
+ .remove = max8997_muic_remove,
};
module_platform_driver(max8997_muic_driver);
diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
index 4ebfb2273672..76b2d390f6ec 100644
--- a/drivers/firewire/nosy.c
+++ b/drivers/firewire/nosy.c
@@ -529,7 +529,7 @@ remove_card(struct pci_dev *dev)
#define RCV_BUFFER_SIZE (16 * 1024)
-static int __devinit
+static int
add_card(struct pci_dev *dev, const struct pci_device_id *unused)
{
struct pcilynx *lynx;
@@ -683,7 +683,7 @@ fail_disable:
return ret;
}
-static struct pci_device_id pci_table[] __devinitdata = {
+static struct pci_device_id pci_table[] = {
{
.vendor = PCI_VENDOR_ID_TI,
.device = PCI_DEVICE_ID_TI_PCILYNX,
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 834e71d2324d..f25610bb3148 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -3537,7 +3537,7 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {}
static inline void pmac_ohci_off(struct pci_dev *dev) {}
#endif /* CONFIG_PPC_PMAC */
-static int __devinit pci_probe(struct pci_dev *dev,
+static int pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
struct fw_ohci *ohci;
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 1162d6b3bf85..bb1b392f5cda 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
struct sbp2_logical_unit *lu = sdev->hostdata;
sdev->use_10_for_rw = 1;
+ sdev->no_report_opcodes = 1;
+ sdev->no_write_same = 1;
if (sbp2_param_exclusive_login)
sdev->manage_start_stop = 1;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f11d8e3b4041..14a6c2913e49 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -49,6 +49,10 @@ config OF_GPIO
def_bool y
depends on OF
+config GPIO_ACPI
+ def_bool y
+ depends on ACPI
+
config DEBUG_GPIO
bool "Debug GPIO calls"
depends on DEBUG_KERNEL
@@ -86,11 +90,26 @@ config GPIO_DA9052
help
Say yes here to enable the GPIO driver for the DA9052 chip.
+config GPIO_DA9055
+ tristate "Dialog Semiconductor DA9055 GPIO"
+ depends on MFD_DA9055
+ help
+ Say yes here to enable the GPIO driver for the DA9055 chip.
+
+ The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
+ be controller by this driver.
+
+ If driver is built as a module it will be called gpio-da9055.
+
config GPIO_MAX730X
tristate
comment "Memory mapped GPIO drivers:"
+config GPIO_CLPS711X
+ def_bool y
+ depends on ARCH_CLPS711X
+
config GPIO_GENERIC_PLATFORM
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
select GPIO_GENERIC
@@ -170,7 +189,7 @@ config GPIO_MXS
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
- depends on ARM_AMBA
+ depends on ARM && ARM_AMBA
select GENERIC_IRQ_CHIP
help
Say yes here to support the PrimeCell PL061 GPIO device
@@ -181,6 +200,13 @@ config GPIO_PXA
help
Say yes here to support the PXA GPIO device
+config GPIO_SPEAR_SPICS
+ bool "ST SPEAr13xx SPI Chip Select as GPIO support"
+ depends on PLAT_SPEAR
+ select GENERIC_IRQ_CHIP
+ help
+ Say yes here to support ST SPEAr SPI Chip Select as GPIO device
+
config GPIO_STA2X11
bool "STA2x11/ConneXt GPIO support"
depends on MFD_STA2X11
@@ -189,6 +215,14 @@ config GPIO_STA2X11
Say yes here to support the STA2x11/ConneXt GPIO device.
The GPIO module has 128 GPIO pins with alternate functions.
+config GPIO_TS5500
+ tristate "TS-5500 DIO blocks and compatibles"
+ help
+ This driver supports Digital I/O exposed by pin blocks found on some
+ Technologic Systems platforms. It includes, but is not limited to, 3
+ blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
+ LCD port.
+
config GPIO_VT8500
bool "VIA/Wondermedia SoC GPIO Support"
depends on ARCH_VT8500
@@ -466,7 +500,7 @@ config GPIO_ADP5588_IRQ
config GPIO_ADNP
tristate "Avionic Design N-bit GPIO expander"
- depends on I2C && OF
+ depends on I2C && OF_GPIO
help
This option enables support for N GPIOs found on Avionic Design
I2C GPIO expanders. The register space will be extended by powers
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9aeed6707326..76b344683251 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
+obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
@@ -16,8 +17,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
+obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
+obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
@@ -57,6 +60,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
+obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
@@ -68,6 +72,7 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
+obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index f05e54258ffb..464be961f605 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -105,7 +105,7 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,
return 0;
}
-static int __devinit gen_74x164_probe(struct spi_device *spi)
+static int gen_74x164_probe(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
struct gen_74x164_chip_platform_data *pdata;
@@ -181,7 +181,7 @@ exit_destroy:
return ret;
}
-static int __devexit gen_74x164_remove(struct spi_device *spi)
+static int gen_74x164_remove(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
int ret;
@@ -215,7 +215,7 @@ static struct spi_driver gen_74x164_driver = {
.of_match_table = of_match_ptr(gen_74x164_dt_ids),
},
.probe = gen_74x164_probe,
- .remove = __devexit_p(gen_74x164_remove),
+ .remove = gen_74x164_remove,
};
module_spi_driver(gen_74x164_driver);
diff --git a/drivers/gpio/gpio-ab8500.c b/drivers/gpio/gpio-ab8500.c
index 050c05d91896..983ad425f0ac 100644
--- a/drivers/gpio/gpio-ab8500.c
+++ b/drivers/gpio/gpio-ab8500.c
@@ -402,7 +402,7 @@ static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
}
}
-static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+static int ab8500_gpio_probe(struct platform_device *pdev)
{
struct ab8500_platform_data *ab8500_pdata =
dev_get_platdata(pdev->dev.parent);
@@ -474,7 +474,7 @@ out_free:
* ab8500_gpio_remove() - remove Ab8500-gpio driver
* @pdev : Platform device registered
*/
-static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+static int ab8500_gpio_remove(struct platform_device *pdev)
{
struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
int ret;
@@ -499,7 +499,7 @@ static struct platform_driver ab8500_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_gpio_probe,
- .remove = __devexit_p(ab8500_gpio_remove),
+ .remove = ab8500_gpio_remove,
};
static int __init ab8500_gpio_init(void)
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 3df88336415e..e60567fc5073 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -516,7 +516,7 @@ static void adnp_irq_teardown(struct adnp *adnp)
irq_domain_remove(adnp->domain);
}
-static __devinit int adnp_i2c_probe(struct i2c_client *client,
+static int adnp_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device_node *np = client->dev.of_node;
@@ -563,7 +563,7 @@ teardown:
return err;
}
-static __devexit int adnp_i2c_remove(struct i2c_client *client)
+static int adnp_i2c_remove(struct i2c_client *client)
{
struct adnp *adnp = i2c_get_clientdata(client);
struct device_node *np = client->dev.of_node;
@@ -582,13 +582,13 @@ static __devexit int adnp_i2c_remove(struct i2c_client *client)
return 0;
}
-static const struct i2c_device_id adnp_i2c_id[] __devinitconst = {
+static const struct i2c_device_id adnp_i2c_id[] = {
{ "gpio-adnp" },
{ },
};
MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
-static const struct of_device_id adnp_of_match[] __devinitconst = {
+static const struct of_device_id adnp_of_match[] = {
{ .compatible = "ad,gpio-adnp", },
{ },
};
@@ -601,7 +601,7 @@ static struct i2c_driver adnp_i2c_driver = {
.of_match_table = of_match_ptr(adnp_of_match),
},
.probe = adnp_i2c_probe,
- .remove = __devexit_p(adnp_i2c_remove),
+ .remove = adnp_i2c_remove,
.id_table = adnp_i2c_id,
};
module_i2c_driver(adnp_i2c_driver);
diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c
index 2f263cc32561..8afa95f831b1 100644
--- a/drivers/gpio/gpio-adp5520.c
+++ b/drivers/gpio/gpio-adp5520.c
@@ -87,7 +87,7 @@ static int adp5520_gpio_direction_output(struct gpio_chip *chip,
return ret;
}
-static int __devinit adp5520_gpio_probe(struct platform_device *pdev)
+static int adp5520_gpio_probe(struct platform_device *pdev)
{
struct adp5520_gpio_platform_data *pdata = pdev->dev.platform_data;
struct adp5520_gpio *dev;
@@ -167,7 +167,7 @@ err:
return ret;
}
-static int __devexit adp5520_gpio_remove(struct platform_device *pdev)
+static int adp5520_gpio_remove(struct platform_device *pdev)
{
struct adp5520_gpio *dev;
int ret;
@@ -190,7 +190,7 @@ static struct platform_driver adp5520_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = adp5520_gpio_probe,
- .remove = __devexit_p(adp5520_gpio_remove),
+ .remove = adp5520_gpio_remove,
};
module_platform_driver(adp5520_gpio_driver);
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index eeedad42913e..2ba56987db04 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -346,7 +346,7 @@ static void adp5588_irq_teardown(struct adp5588_gpio *dev)
}
#endif /* CONFIG_GPIO_ADP5588_IRQ */
-static int __devinit adp5588_gpio_probe(struct i2c_client *client,
+static int adp5588_gpio_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
@@ -438,7 +438,7 @@ err:
return ret;
}
-static int __devexit adp5588_gpio_remove(struct i2c_client *client)
+static int adp5588_gpio_remove(struct i2c_client *client)
{
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
struct adp5588_gpio *dev = i2c_get_clientdata(client);
@@ -479,7 +479,7 @@ static struct i2c_driver adp5588_gpio_driver = {
.name = DRV_NAME,
},
.probe = adp5588_gpio_probe,
- .remove = __devexit_p(adp5588_gpio_remove),
+ .remove = adp5588_gpio_remove,
.id_table = adp5588_gpio_id,
};
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 8740d2eb06f8..0ea853f68db2 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -94,7 +94,7 @@ static struct gpio_chip template_chip = {
.can_sleep = 1,
};
-static int __devinit arizona_gpio_probe(struct platform_device *pdev)
+static int arizona_gpio_probe(struct platform_device *pdev)
{
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata = arizona->dev->platform_data;
@@ -141,7 +141,7 @@ err:
return ret;
}
-static int __devexit arizona_gpio_remove(struct platform_device *pdev)
+static int arizona_gpio_remove(struct platform_device *pdev)
{
struct arizona_gpio *arizona_gpio = platform_get_drvdata(pdev);
@@ -152,7 +152,7 @@ static struct platform_driver arizona_gpio_driver = {
.driver.name = "arizona-gpio",
.driver.owner = THIS_MODULE,
.probe = arizona_gpio_probe,
- .remove = __devexit_p(arizona_gpio_remove),
+ .remove = arizona_gpio_remove,
};
module_platform_driver(arizona_gpio_driver);
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
new file mode 100644
index 000000000000..ce63b75b13f5
--- /dev/null
+++ b/drivers/gpio/gpio-clps711x.c
@@ -0,0 +1,199 @@
+/*
+ * CLPS711X GPIO driver
+ *
+ * Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+
+#define CLPS711X_GPIO_PORTS 5
+#define CLPS711X_GPIO_NAME "gpio-clps711x"
+
+struct clps711x_gpio {
+ struct gpio_chip chip[CLPS711X_GPIO_PORTS];
+ spinlock_t lock;
+};
+
+static void __iomem *clps711x_ports[] = {
+ CLPS711X_VIRT_BASE + PADR,
+ CLPS711X_VIRT_BASE + PBDR,
+ CLPS711X_VIRT_BASE + PCDR,
+ CLPS711X_VIRT_BASE + PDDR,
+ CLPS711X_VIRT_BASE + PEDR,
+};
+
+static void __iomem *clps711x_pdirs[] = {
+ CLPS711X_VIRT_BASE + PADDR,
+ CLPS711X_VIRT_BASE + PBDDR,
+ CLPS711X_VIRT_BASE + PCDDR,
+ CLPS711X_VIRT_BASE + PDDDR,
+ CLPS711X_VIRT_BASE + PEDDR,
+};
+
+#define clps711x_port(x) clps711x_ports[x->base / 8]
+#define clps711x_pdir(x) clps711x_pdirs[x->base / 8]
+
+static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
+{
+ return !!(readb(clps711x_port(chip)) & (1 << offset));
+}
+
+static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ int tmp;
+ unsigned long flags;
+ struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+ if (value)
+ tmp |= 1 << offset;
+ writeb(tmp, clps711x_port(chip));
+ spin_unlock_irqrestore(&gpio->lock, flags);
+}
+
+static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+ int tmp;
+ unsigned long flags;
+ struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+ writeb(tmp, clps711x_pdir(chip));
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ int tmp;
+ unsigned long flags;
+ struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+ writeb(tmp, clps711x_pdir(chip));
+ tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+ if (value)
+ tmp |= 1 << offset;
+ writeb(tmp, clps711x_port(chip));
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset)
+{
+ int tmp;
+ unsigned long flags;
+ struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ tmp = readb(clps711x_pdir(chip)) | (1 << offset);
+ writeb(tmp, clps711x_pdir(chip));
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ int tmp;
+ unsigned long flags;
+ struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
+
+ spin_lock_irqsave(&gpio->lock, flags);
+ tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
+ writeb(tmp, clps711x_pdir(chip));
+ tmp = readb(clps711x_port(chip)) & ~(1 << offset);
+ if (value)
+ tmp |= 1 << offset;
+ writeb(tmp, clps711x_port(chip));
+ spin_unlock_irqrestore(&gpio->lock, flags);
+
+ return 0;
+}
+
+static struct {
+ char *name;
+ int nr;
+ int inv_dir;
+} clps711x_gpio_ports[] __initconst = {
+ { "PORTA", 8, 0, },
+ { "PORTB", 8, 0, },
+ { "PORTC", 8, 0, },
+ { "PORTD", 8, 1, },
+ { "PORTE", 3, 0, },
+};
+
+static int __init gpio_clps711x_init(void)
+{
+ int i;
+ struct platform_device *pdev;
+ struct clps711x_gpio *gpio;
+
+ pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
+ if (!pdev) {
+ pr_err("Cannot create platform device: %s\n",
+ CLPS711X_GPIO_NAME);
+ return -ENOMEM;
+ }
+
+ platform_device_add(pdev);
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
+ GFP_KERNEL);
+ if (!gpio) {
+ dev_err(&pdev->dev, "GPIO allocating memory error\n");
+ platform_device_unregister(pdev);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, gpio);
+
+ spin_lock_init(&gpio->lock);
+
+ for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
+ gpio->chip[i].owner = THIS_MODULE;
+ gpio->chip[i].dev = &pdev->dev;
+ gpio->chip[i].label = clps711x_gpio_ports[i].name;
+ gpio->chip[i].base = i * 8;
+ gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr;
+ gpio->chip[i].get = gpio_clps711x_get;
+ gpio->chip[i].set = gpio_clps711x_set;
+ if (!clps711x_gpio_ports[i].inv_dir) {
+ gpio->chip[i].direction_input = gpio_clps711x_dir_in;
+ gpio->chip[i].direction_output = gpio_clps711x_dir_out;
+ } else {
+ gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv;
+ gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv;
+ }
+ WARN_ON(gpiochip_add(&gpio->chip[i]));
+ }
+
+ dev_info(&pdev->dev, "GPIO driver initialized\n");
+
+ return 0;
+}
+arch_initcall(gpio_clps711x_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("CLPS711X GPIO driver");
diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c
index 19eda1bbe343..c0a3aeba6f21 100644
--- a/drivers/gpio/gpio-cs5535.c
+++ b/drivers/gpio/gpio-cs5535.c
@@ -300,7 +300,7 @@ static struct cs5535_gpio_chip cs5535_gpio_chip = {
},
};
-static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
+static int cs5535_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
int err = -EIO;
@@ -355,7 +355,7 @@ done:
return err;
}
-static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
+static int cs5535_gpio_remove(struct platform_device *pdev)
{
struct resource *r;
int err;
@@ -378,7 +378,7 @@ static struct platform_driver cs5535_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = cs5535_gpio_probe,
- .remove = __devexit_p(cs5535_gpio_remove),
+ .remove = cs5535_gpio_remove,
};
module_platform_driver(cs5535_gpio_driver);
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 24b8c2974047..a05aacd2777a 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -188,7 +188,7 @@ static int da9052_gpio_to_irq(struct gpio_chip *gc, u32 offset)
return da9052->irq_base + DA9052_IRQ_GPI0 + offset;
}
-static struct gpio_chip reference_gp __devinitdata = {
+static struct gpio_chip reference_gp = {
.label = "da9052-gpio",
.owner = THIS_MODULE,
.get = da9052_gpio_get,
@@ -201,7 +201,7 @@ static struct gpio_chip reference_gp __devinitdata = {
.base = -1,
};
-static int __devinit da9052_gpio_probe(struct platform_device *pdev)
+static int da9052_gpio_probe(struct platform_device *pdev)
{
struct da9052_gpio *gpio;
struct da9052_pdata *pdata;
@@ -229,7 +229,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit da9052_gpio_remove(struct platform_device *pdev)
+static int da9052_gpio_remove(struct platform_device *pdev)
{
struct da9052_gpio *gpio = platform_get_drvdata(pdev);
@@ -238,7 +238,7 @@ static int __devexit da9052_gpio_remove(struct platform_device *pdev)
static struct platform_driver da9052_gpio_driver = {
.probe = da9052_gpio_probe,
- .remove = __devexit_p(da9052_gpio_remove),
+ .remove = da9052_gpio_remove,
.driver = {
.name = "da9052-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c
new file mode 100644
index 000000000000..55d83c7d9c7f
--- /dev/null
+++ b/drivers/gpio/gpio-da9055.c
@@ -0,0 +1,204 @@
+/*
+ * GPIO Driver for Dialog DA9055 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_VDD_IO 0x0
+#define DA9055_PUSH_PULL 0x3
+#define DA9055_ACT_LOW 0x0
+#define DA9055_GPI 0x1
+#define DA9055_PORT_MASK 0x3
+#define DA9055_PORT_SHIFT(offset) (4 * (offset % 2))
+
+#define DA9055_INPUT DA9055_GPI
+#define DA9055_OUTPUT DA9055_PUSH_PULL
+#define DA9055_IRQ_GPI0 3
+
+struct da9055_gpio {
+ struct da9055 *da9055;
+ struct gpio_chip gp;
+};
+
+static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct da9055_gpio, gp);
+}
+
+static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+ struct da9055_gpio *gpio = to_da9055_gpio(gc);
+ int gpio_direction = 0;
+ int ret;
+
+ /* Get GPIO direction */
+ ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
+ if (ret < 0)
+ return ret;
+
+ gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
+ gpio_direction >>= DA9055_PORT_SHIFT(offset);
+ switch (gpio_direction) {
+ case DA9055_INPUT:
+ ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
+ if (ret < 0)
+ return ret;
+ break;
+ case DA9055_OUTPUT:
+ ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
+ if (ret < 0)
+ return ret;
+ }
+
+ return ret & (1 << offset);
+
+}
+
+static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct da9055_gpio *gpio = to_da9055_gpio(gc);
+
+ da9055_reg_update(gpio->da9055,
+ DA9055_REG_GPIO_MODE0_2,
+ 1 << offset,
+ value << offset);
+}
+
+static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct da9055_gpio *gpio = to_da9055_gpio(gc);
+ unsigned char reg_byte;
+
+ reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
+ << DA9055_PORT_SHIFT(offset);
+
+ return da9055_reg_update(gpio->da9055, (offset >> 1) +
+ DA9055_REG_GPIO0_1,
+ DA9055_PORT_MASK <<
+ DA9055_PORT_SHIFT(offset),
+ reg_byte);
+}
+
+static int da9055_gpio_direction_output(struct gpio_chip *gc,
+ unsigned offset, int value)
+{
+ struct da9055_gpio *gpio = to_da9055_gpio(gc);
+ unsigned char reg_byte;
+ int ret;
+
+ reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
+ << DA9055_PORT_SHIFT(offset);
+
+ ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
+ DA9055_REG_GPIO0_1,
+ DA9055_PORT_MASK <<
+ DA9055_PORT_SHIFT(offset),
+ reg_byte);
+ if (ret < 0)
+ return ret;
+
+ da9055_gpio_set(gc, offset, value);
+
+ return 0;
+}
+
+static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
+{
+ struct da9055_gpio *gpio = to_da9055_gpio(gc);
+ struct da9055 *da9055 = gpio->da9055;
+
+ return regmap_irq_get_virq(da9055->irq_data,
+ DA9055_IRQ_GPI0 + offset);
+}
+
+static struct gpio_chip reference_gp __devinitdata = {
+ .label = "da9055-gpio",
+ .owner = THIS_MODULE,
+ .get = da9055_gpio_get,
+ .set = da9055_gpio_set,
+ .direction_input = da9055_gpio_direction_input,
+ .direction_output = da9055_gpio_direction_output,
+ .to_irq = da9055_gpio_to_irq,
+ .can_sleep = 1,
+ .ngpio = 3,
+ .base = -1,
+};
+
+static int __devinit da9055_gpio_probe(struct platform_device *pdev)
+{
+ struct da9055_gpio *gpio;
+ struct da9055_pdata *pdata;
+ int ret;
+
+ gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+ if (gpio == NULL)
+ return -ENOMEM;
+
+ gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
+ pdata = gpio->da9055->dev->platform_data;
+
+ gpio->gp = reference_gp;
+ if (pdata && pdata->gpio_base)
+ gpio->gp.base = pdata->gpio_base;
+
+ ret = gpiochip_add(&gpio->gp);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ goto err_mem;
+ }
+
+ platform_set_drvdata(pdev, gpio);
+
+ return 0;
+
+err_mem:
+ return ret;
+}
+
+static int __devexit da9055_gpio_remove(struct platform_device *pdev)
+{
+ struct da9055_gpio *gpio = platform_get_drvdata(pdev);
+
+ return gpiochip_remove(&gpio->gp);
+}
+
+static struct platform_driver da9055_gpio_driver = {
+ .probe = da9055_gpio_probe,
+ .remove = __devexit_p(da9055_gpio_remove),
+ .driver = {
+ .name = "da9055-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9055_gpio_init(void)
+{
+ return platform_driver_register(&da9055_gpio_driver);
+}
+subsys_initcall(da9055_gpio_init);
+
+static void __exit da9055_gpio_exit(void)
+{
+ platform_driver_unregister(&da9055_gpio_driver);
+}
+module_exit(da9055_gpio_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-gpio");
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index efb4c2d0d132..bdc8302e711a 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -35,7 +35,6 @@
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;
@@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
{
- return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
+ return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
}
static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
@@ -234,41 +233,7 @@ 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 (p->irq_base < 0) {
- dev_err(&pdev->dev, "cannot get irq_desc\n");
- return p->irq_base;
- }
- 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 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)
+static int em_gio_probe(struct platform_device *pdev)
{
struct gpio_em_config *pdata = pdev->dev.platform_data;
struct em_gio_priv *p;
@@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev)
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) {
+ p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+ pdata->number_of_pins,
+ &em_gio_irq_domain_ops, p);
+ if (!p->irq_domain) {
+ ret = -ENXIO;
dev_err(&pdev->dev, "cannot initialize irq domain\n");
goto err3;
}
@@ -364,7 +332,7 @@ err6:
err5:
free_irq(irq[0]->start, pdev);
err4:
- em_gio_irq_domain_cleanup(p);
+ irq_domain_remove(p->irq_domain);
err3:
iounmap(p->base1);
err2:
@@ -375,7 +343,7 @@ err0:
return ret;
}
-static int __devexit em_gio_remove(struct platform_device *pdev)
+static int em_gio_remove(struct platform_device *pdev)
{
struct em_gio_priv *p = platform_get_drvdata(pdev);
struct resource *irq[2];
@@ -390,7 +358,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
free_irq(irq[1]->start, pdev);
free_irq(irq[0]->start, pdev);
- em_gio_irq_domain_cleanup(p);
+ irq_domain_remove(p->irq_domain);
iounmap(p->base1);
iounmap(p->base0);
kfree(p);
@@ -399,7 +367,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
static struct platform_driver em_gio_device_driver = {
.probe = em_gio_probe,
- .remove = __devexit_p(em_gio_remove),
+ .remove = em_gio_remove,
.driver = {
.name = "em_gio",
}
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 9fe5b8fe9be8..56b98eebe1fc 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -340,7 +340,7 @@ static int ep93xx_gpio_add_bank(struct bgpio_chip *bgc, struct device *dev,
return gpiochip_add(&bgc->gc);
}
-static int __devinit ep93xx_gpio_probe(struct platform_device *pdev)
+static int ep93xx_gpio_probe(struct platform_device *pdev)
{
struct ep93xx_gpio *ep93xx_gpio;
struct resource *res;
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 82e2e4fe599e..05fcc0f247ca 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -444,7 +444,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
return ret;
}
-static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
+static int bgpio_pdev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *r;
@@ -507,7 +507,7 @@ static int __devinit bgpio_pdev_probe(struct platform_device *pdev)
return gpiochip_add(&bgc->gc);
}
-static int __devexit bgpio_pdev_remove(struct platform_device *pdev)
+static int bgpio_pdev_remove(struct platform_device *pdev)
{
struct bgpio_chip *bgc = platform_get_drvdata(pdev);
@@ -527,7 +527,7 @@ static struct platform_driver bgpio_driver = {
},
.id_table = bgpio_id_table,
.probe = bgpio_pdev_probe,
- .remove = __devexit_p(bgpio_pdev_remove),
+ .remove = bgpio_pdev_remove,
};
module_platform_driver(bgpio_driver);
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index d4d617966696..6cc87ac8e019 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -238,7 +238,7 @@ static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
ichx_write_bit(GPIO_LVL, nr, val, 0);
}
-static void __devinit ichx_gpiolib_setup(struct gpio_chip *chip)
+static void ichx_gpiolib_setup(struct gpio_chip *chip)
{
chip->owner = THIS_MODULE;
chip->label = DRV_NAME;
@@ -313,7 +313,7 @@ static struct ichx_desc intel5_desc = {
.ngpio = 76,
};
-static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+static int ichx_gpio_request_regions(struct resource *res_base,
const char *name, u8 use_gpio)
{
int i;
@@ -353,7 +353,7 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
}
}
-static int __devinit ichx_gpio_probe(struct platform_device *pdev)
+static int ichx_gpio_probe(struct platform_device *pdev)
{
struct resource *res_base, *res_pm;
int err;
@@ -442,7 +442,7 @@ add_err:
return err;
}
-static int __devexit ichx_gpio_remove(struct platform_device *pdev)
+static int ichx_gpio_remove(struct platform_device *pdev)
{
int err;
@@ -467,7 +467,7 @@ static struct platform_driver ichx_gpio_driver = {
.name = DRV_NAME,
},
.probe = ichx_gpio_probe,
- .remove = __devexit_p(ichx_gpio_remove),
+ .remove = ichx_gpio_remove,
};
module_platform_driver(ichx_gpio_driver);
diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c
index f2f000dd70b3..7d0a04169a35 100644
--- a/drivers/gpio/gpio-janz-ttl.c
+++ b/drivers/gpio/gpio-janz-ttl.c
@@ -108,13 +108,13 @@ static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
spin_unlock(&mod->lock);
}
-static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
+static void ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
{
iowrite16be(reg, &mod->regs->control);
iowrite16be(val, &mod->regs->control);
}
-static void __devinit ttl_setup_device(struct ttl_module *mod)
+static void ttl_setup_device(struct ttl_module *mod)
{
/* reset the device to a known state */
iowrite16be(0x0000, &mod->regs->control);
@@ -140,7 +140,7 @@ static void __devinit ttl_setup_device(struct ttl_module *mod)
ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
}
-static int __devinit ttl_probe(struct platform_device *pdev)
+static int ttl_probe(struct platform_device *pdev)
{
struct janz_platform_data *pdata;
struct device *dev = &pdev->dev;
@@ -211,7 +211,7 @@ out_return:
return ret;
}
-static int __devexit ttl_remove(struct platform_device *pdev)
+static int ttl_remove(struct platform_device *pdev)
{
struct ttl_module *mod = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
@@ -234,7 +234,7 @@ static struct platform_driver ttl_driver = {
.owner = THIS_MODULE,
},
.probe = ttl_probe,
- .remove = __devexit_p(ttl_remove),
+ .remove = ttl_remove,
};
module_platform_driver(ttl_driver);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index 202a99207b7d..e77b2b3e94af 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -332,7 +332,7 @@ static const struct dev_pm_ops lnw_gpio_pm_ops = {
.runtime_idle = lnw_gpio_runtime_idle,
};
-static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
+static int lnw_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
void *base;
@@ -435,7 +435,7 @@ static struct pci_driver lnw_gpio_driver = {
};
-static int __devinit wp_gpio_probe(struct platform_device *pdev)
+static int wp_gpio_probe(struct platform_device *pdev)
{
struct lnw_gpio *lnw;
struct gpio_chip *gc;
@@ -484,7 +484,7 @@ err_kmalloc:
return retval;
}
-static int __devexit wp_gpio_remove(struct platform_device *pdev)
+static int wp_gpio_remove(struct platform_device *pdev)
{
struct lnw_gpio *lnw = platform_get_drvdata(pdev);
int err;
@@ -499,7 +499,7 @@ static int __devexit wp_gpio_remove(struct platform_device *pdev)
static struct platform_driver wp_gpio_driver = {
.probe = wp_gpio_probe,
- .remove = __devexit_p(wp_gpio_remove),
+ .remove = wp_gpio_remove,
.driver = {
.name = "wp_gpio",
.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 3644e0dcb3dd..36d7dee07b28 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -542,7 +542,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
return gpiospec->args[1];
}
-static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
+static int lpc32xx_gpio_probe(struct platform_device *pdev)
{
int i;
@@ -559,7 +559,7 @@ static int __devinit lpc32xx_gpio_probe(struct platform_device *pdev)
}
#ifdef CONFIG_OF
-static struct of_device_id lpc32xx_gpio_of_match[] __devinitdata = {
+static struct of_device_id lpc32xx_gpio_of_match[] = {
{ .compatible = "nxp,lpc3220-gpio", },
{ },
};
diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c
index a5ca0ab1b372..4b6b9a04e326 100644
--- a/drivers/gpio/gpio-max7300.c
+++ b/drivers/gpio/gpio-max7300.c
@@ -31,7 +31,7 @@ static int max7300_i2c_read(struct device *dev, unsigned int reg)
return i2c_smbus_read_byte_data(client, reg);
}
-static int __devinit max7300_probe(struct i2c_client *client,
+static int max7300_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max7301 *ts;
@@ -55,7 +55,7 @@ static int __devinit max7300_probe(struct i2c_client *client,
return ret;
}
-static int __devexit max7300_remove(struct i2c_client *client)
+static int max7300_remove(struct i2c_client *client)
{
return __max730x_remove(&client->dev);
}
@@ -72,7 +72,7 @@ static struct i2c_driver max7300_driver = {
.owner = THIS_MODULE,
},
.probe = max7300_probe,
- .remove = __devexit_p(max7300_remove),
+ .remove = max7300_remove,
.id_table = max7300_id,
};
diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c
index 741acfcbe761..c6c535c1310e 100644
--- a/drivers/gpio/gpio-max7301.c
+++ b/drivers/gpio/gpio-max7301.c
@@ -50,7 +50,7 @@ static int max7301_spi_read(struct device *dev, unsigned int reg)
return word & 0xff;
}
-static int __devinit max7301_probe(struct spi_device *spi)
+static int max7301_probe(struct spi_device *spi)
{
struct max7301 *ts;
int ret;
@@ -75,7 +75,7 @@ static int __devinit max7301_probe(struct spi_device *spi)
return ret;
}
-static int __devexit max7301_remove(struct spi_device *spi)
+static int max7301_remove(struct spi_device *spi)
{
return __max730x_remove(&spi->dev);
}
@@ -92,7 +92,7 @@ static struct spi_driver max7301_driver = {
.owner = THIS_MODULE,
},
.probe = max7301_probe,
- .remove = __devexit_p(max7301_remove),
+ .remove = max7301_remove,
.id_table = max7301_id,
};
diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c
index 05e2dac60b3b..00092342b84c 100644
--- a/drivers/gpio/gpio-max730x.c
+++ b/drivers/gpio/gpio-max730x.c
@@ -160,17 +160,13 @@ static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
mutex_unlock(&ts->lock);
}
-int __devinit __max730x_probe(struct max7301 *ts)
+int __max730x_probe(struct max7301 *ts)
{
struct device *dev = ts->dev;
struct max7301_platform_data *pdata;
int i, ret;
pdata = dev->platform_data;
- if (!pdata || !pdata->base) {
- dev_err(dev, "incorrect or missing platform data\n");
- return -EINVAL;
- }
mutex_init(&ts->lock);
dev_set_drvdata(dev, ts);
@@ -178,7 +174,12 @@ int __devinit __max730x_probe(struct max7301 *ts)
/* Power up the chip and disable IRQ output */
ts->write(dev, 0x04, 0x01);
- ts->input_pullup_active = pdata->input_pullup_active;
+ if (pdata) {
+ ts->input_pullup_active = pdata->input_pullup_active;
+ ts->chip.base = pdata->base;
+ } else {
+ ts->chip.base = -1;
+ }
ts->chip.label = dev->driver->name;
ts->chip.direction_input = max7301_direction_input;
@@ -186,7 +187,6 @@ int __devinit __max730x_probe(struct max7301 *ts)
ts->chip.direction_output = max7301_direction_output;
ts->chip.set = max7301_set;
- ts->chip.base = pdata->base;
ts->chip.ngpio = PIN_NUMBER;
ts->chip.can_sleep = 1;
ts->chip.dev = dev;
@@ -226,7 +226,7 @@ exit_destroy:
}
EXPORT_SYMBOL_GPL(__max730x_probe);
-int __devexit __max730x_remove(struct device *dev)
+int __max730x_remove(struct device *dev)
{
struct max7301 *ts = dev_get_drvdata(dev);
int ret;
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index 9504120812a5..1e0467ce4c37 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -526,7 +526,7 @@ static void max732x_irq_teardown(struct max732x_chip *chip)
}
#endif
-static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
+static int max732x_setup_gpio(struct max732x_chip *chip,
const struct i2c_device_id *id,
unsigned gpio_start)
{
@@ -574,7 +574,7 @@ static int __devinit max732x_setup_gpio(struct max732x_chip *chip,
return port;
}
-static int __devinit max732x_probe(struct i2c_client *client,
+static int max732x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max732x_platform_data *pdata;
@@ -651,7 +651,7 @@ out_failed:
return ret;
}
-static int __devexit max732x_remove(struct i2c_client *client)
+static int max732x_remove(struct i2c_client *client)
{
struct max732x_platform_data *pdata = client->dev.platform_data;
struct max732x_chip *chip = i2c_get_clientdata(client);
@@ -690,7 +690,7 @@ static struct i2c_driver max732x_driver = {
.owner = THIS_MODULE,
},
.probe = max732x_probe,
- .remove = __devexit_p(max732x_remove),
+ .remove = max732x_remove,
.id_table = max732x_id,
};
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 2de57ce5feb6..6a8fdc26ae6a 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -80,7 +80,7 @@ static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value)
mutex_unlock(&mc->lock);
}
-static int __devinit mc33880_probe(struct spi_device *spi)
+static int mc33880_probe(struct spi_device *spi)
{
struct mc33880 *mc;
struct mc33880_platform_data *pdata;
@@ -147,7 +147,7 @@ exit_destroy:
return ret;
}
-static int __devexit mc33880_remove(struct spi_device *spi)
+static int mc33880_remove(struct spi_device *spi)
{
struct mc33880 *mc;
int ret;
@@ -175,7 +175,7 @@ static struct spi_driver mc33880_driver = {
.owner = THIS_MODULE,
},
.probe = mc33880_probe,
- .remove = __devexit_p(mc33880_remove),
+ .remove = mc33880_remove,
};
static int __init mc33880_init(void)
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c
index 0f425189de11..3cea0ea79e80 100644
--- a/drivers/gpio/gpio-mcp23s08.c
+++ b/drivers/gpio/gpio-mcp23s08.c
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
/*----------------------------------------------------------------------*/
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
{
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
break;
#endif /* CONFIG_SPI_MASTER */
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
case MCP_TYPE_008:
mcp->ops = &mcp23008_ops;
mcp->chip.ngpio = 8;
@@ -473,9 +473,9 @@ fail:
/*----------------------------------------------------------------------*/
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
-static int __devinit mcp230xx_probe(struct i2c_client *client,
+static int mcp230xx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct mcp23s08_platform_data *pdata;
@@ -508,7 +508,7 @@ fail:
return status;
}
-static int __devexit mcp230xx_remove(struct i2c_client *client)
+static int mcp230xx_remove(struct i2c_client *client)
{
struct mcp23s08 *mcp = i2c_get_clientdata(client);
int status;
@@ -533,7 +533,7 @@ static struct i2c_driver mcp230xx_driver = {
.owner = THIS_MODULE,
},
.probe = mcp230xx_probe,
- .remove = __devexit_p(mcp230xx_remove),
+ .remove = mcp230xx_remove,
.id_table = mcp230xx_id,
};
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 6a29ee1847be..b73366523fae 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -385,7 +385,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
return ret;
}
-static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
+static void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
@@ -406,7 +406,7 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
+static int ioh_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
@@ -517,7 +517,7 @@ err_pci_enable:
return ret;
}
-static void __devexit ioh_gpio_remove(struct pci_dev *pdev)
+static void ioh_gpio_remove(struct pci_dev *pdev)
{
int err;
int i;
@@ -606,7 +606,7 @@ static struct pci_driver ioh_gpio_driver = {
.name = "ml_ioh_gpio",
.id_table = ioh_gpio_pcidev_id,
.probe = ioh_gpio_probe,
- .remove = __devexit_p(ioh_gpio_remove),
+ .remove = ioh_gpio_remove,
.suspend = ioh_gpio_suspend,
.resume = ioh_gpio_resume
};
diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c
index 2c7cef367fc0..42647f26c9e0 100644
--- a/drivers/gpio/gpio-mpc5200.c
+++ b/drivers/gpio/gpio-mpc5200.c
@@ -148,7 +148,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
return 0;
}
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
{
struct mpc52xx_gpiochip *chip;
struct mpc52xx_gpio_wkup __iomem *regs;
@@ -308,7 +308,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
return 0;
}
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
+static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
{
struct mpc52xx_gpiochip *chip;
struct gpio_chip *gc;
diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c
index b38986285868..27ea7b9257ff 100644
--- a/drivers/gpio/gpio-msic.c
+++ b/drivers/gpio/gpio-msic.c
@@ -256,7 +256,7 @@ static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
chip->irq_eoi(data);
}
-static int __devinit platform_msic_gpio_probe(struct platform_device *pdev)
+static int platform_msic_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct intel_msic_gpio_pdata *pdata = dev->platform_data;
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 38305beb4375..55a7e7769af6 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -352,7 +352,7 @@ static struct irq_chip msm_gpio_irq_chip = {
.irq_set_wake = msm_gpio_irq_set_wake,
};
-static int __devinit msm_gpio_probe(struct platform_device *dev)
+static int msm_gpio_probe(struct platform_device *dev)
{
int i, irq, ret;
@@ -376,7 +376,7 @@ static int __devinit msm_gpio_probe(struct platform_device *dev)
return 0;
}
-static int __devexit msm_gpio_remove(struct platform_device *dev)
+static int msm_gpio_remove(struct platform_device *dev)
{
int ret = gpiochip_remove(&msm_gpio.gpio_chip);
@@ -390,7 +390,7 @@ static int __devexit msm_gpio_remove(struct platform_device *dev)
static struct platform_driver msm_gpio_driver = {
.probe = msm_gpio_probe,
- .remove = __devexit_p(msm_gpio_remove),
+ .remove = msm_gpio_remove,
.driver = {
.name = "msmgpio",
.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index cf7afb9eb61a..d767b534c4af 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
return mvchip->membase + GPIO_OUT_OFF;
}
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+ return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
{
return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -163,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
* Functions implementing the gpio_chip methods
*/
-int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
{
return pinctrl_request_gpio(chip->base + pin);
}
-void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
{
pinctrl_free_gpio(chip->base + pin);
}
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
return (u >> pin) & 1;
}
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+ struct mvebu_gpio_chip *mvchip =
+ container_of(chip, struct mvebu_gpio_chip, chip);
+ unsigned long flags;
+ u32 u;
+
+ spin_lock_irqsave(&mvchip->lock, flags);
+ u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+ if (value)
+ u |= 1 << pin;
+ else
+ u &= ~(1 << pin);
+ writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+ spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
{
struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
if (ret)
return ret;
+ mvebu_gpio_blink(chip, pin, 0);
mvebu_gpio_set(chip, pin, value);
spin_lock_irqsave(&mvchip->lock, flags);
@@ -459,7 +482,7 @@ static struct platform_device_id mvebu_gpio_ids[] = {
};
MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
-static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+static struct of_device_id mvebu_gpio_of_match[] = {
{
.compatible = "marvell,orion-gpio",
.data = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
@@ -478,7 +501,7 @@ static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
};
MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
-static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+static int mvebu_gpio_probe(struct platform_device *pdev)
{
struct mvebu_gpio_chip *mvchip;
const struct of_device_id *match;
@@ -523,6 +546,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
mvchip->chip.label = dev_name(&pdev->dev);
mvchip->chip.dev = &pdev->dev;
mvchip->chip.request = mvebu_gpio_request;
+ mvchip->chip.free = mvebu_gpio_free;
mvchip->chip.direction_input = mvebu_gpio_direction_input;
mvchip->chip.get = mvebu_gpio_get;
mvchip->chip.direction_output = mvebu_gpio_direction_output;
@@ -650,8 +674,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
/* Setup irq domain on top of the generic chip. */
- mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
- mvchip->irqbase, 0,
+ mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
+ mvchip->irqbase,
&irq_domain_simple_ops,
mvchip);
if (!mvchip->domain) {
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 80f44bb64a87..7877335c4cc8 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -356,7 +356,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
IRQ_NOREQUEST, 0);
}
-static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
+static void mxc_gpio_get_hw(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxc_gpio_dt_ids, &pdev->dev);
@@ -395,7 +395,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return irq_find_mapping(port->domain, offset);
}
-static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+static int mxc_gpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mxc_gpio_port *port;
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index 796fb13e4815..fa2a63cad32e 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -214,7 +214,7 @@ static const struct of_device_id mxs_gpio_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids);
-static int __devinit mxs_gpio_probe(struct platform_device *pdev)
+static int mxs_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxs_gpio_dt_ids, &pdev->dev);
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index d335af1d4d85..f1fbedb2a6f9 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1012,7 +1012,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
dev_err(bank->dev, "Could not get gpio dbck\n");
}
-static __devinit void
+static void
omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
unsigned int num)
{
@@ -1041,7 +1041,7 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
+static void omap_gpio_chip_init(struct gpio_bank *bank)
{
int j;
static int gpio;
@@ -1089,7 +1089,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank)
static const struct of_device_id omap_gpio_match[];
-static int __devinit omap_gpio_probe(struct platform_device *pdev)
+static int omap_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
@@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
if (!pdata)
return -EINVAL;
- bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
+ bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
if (!bank) {
dev_err(dev, "Memory alloc failed\n");
return -ENOMEM;
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 9c693ae17956..cc102d25ee24 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -16,6 +16,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/i2c.h>
#include <linux/i2c/pca953x.h>
#include <linux/slab.h>
@@ -83,6 +84,7 @@ struct pca953x_chip {
u32 irq_trig_raise;
u32 irq_trig_fall;
int irq_base;
+ struct irq_domain *domain;
#endif
struct i2c_client *client;
@@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
+ chip->irq_mask &= ~(1 << d->hwirq);
}
static void pca953x_irq_unmask(struct irq_data *d)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- chip->irq_mask |= 1 << (d->irq - chip->irq_base);
+ chip->irq_mask |= 1 << d->hwirq;
}
static void pca953x_irq_bus_lock(struct irq_data *d)
@@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
{
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
- u32 level = d->irq - chip->irq_base;
- u32 mask = 1 << level;
+ u32 mask = 1 << d->hwirq;
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
- handle_nested_irq(level + chip->irq_base);
+ handle_nested_irq(irq_find_mapping(chip->domain, level));
pending &= ~(1 << level);
} while (pending);
@@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
if (chip->irq_base < 0)
goto out_failed;
+ chip->domain = irq_domain_add_legacy(client->dev.of_node,
+ chip->gpio_chip.ngpio,
+ chip->irq_base,
+ 0,
+ &irq_domain_simple_ops,
+ NULL);
+ if (!chip->domain) {
+ ret = -ENODEV;
+ goto out_irqdesc_free;
+ }
+
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
int irq = lvl + chip->irq_base;
@@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
- goto out_failed;
+ goto out_irqdesc_free;
}
chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
@@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
return 0;
+out_irqdesc_free:
+ irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
out_failed:
chip->irq_base = -1;
return ret;
@@ -602,7 +616,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
}
#endif
-static int __devinit device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
@@ -621,7 +635,7 @@ out:
return ret;
}
-static int __devinit device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
{
int ret;
u32 val = 0;
@@ -652,7 +666,7 @@ out:
return ret;
}
-static int __devinit pca953x_probe(struct i2c_client *client,
+static int pca953x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca953x_platform_data *pdata;
@@ -751,9 +765,38 @@ static int pca953x_remove(struct i2c_client *client)
return 0;
}
+static const struct of_device_id pca953x_dt_ids[] = {
+ { .compatible = "nxp,pca9534", },
+ { .compatible = "nxp,pca9535", },
+ { .compatible = "nxp,pca9536", },
+ { .compatible = "nxp,pca9537", },
+ { .compatible = "nxp,pca9538", },
+ { .compatible = "nxp,pca9539", },
+ { .compatible = "nxp,pca9554", },
+ { .compatible = "nxp,pca9555", },
+ { .compatible = "nxp,pca9556", },
+ { .compatible = "nxp,pca9557", },
+ { .compatible = "nxp,pca9574", },
+ { .compatible = "nxp,pca9575", },
+
+ { .compatible = "maxim,max7310", },
+ { .compatible = "maxim,max7312", },
+ { .compatible = "maxim,max7313", },
+ { .compatible = "maxim,max7315", },
+
+ { .compatible = "ti,pca6107", },
+ { .compatible = "ti,tca6408", },
+ { .compatible = "ti,tca6416", },
+ { .compatible = "ti,tca6424", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
+
static struct i2c_driver pca953x_driver = {
.driver = {
.name = "pca953x",
+ .of_match_table = pca953x_dt_ids,
},
.probe = pca953x_probe,
.remove = pca953x_remove,
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 16af35cd2b10..a19b7457a726 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -223,11 +223,11 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
struct pcf857x_platform_data *pdata,
- struct device *dev)
+ struct i2c_client *client)
{
int status;
- gpio->irq_domain = irq_domain_add_linear(dev->of_node,
+ gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
gpio->chip.ngpio,
&pcf857x_irq_domain_ops,
NULL);
@@ -235,15 +235,15 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
goto fail;
/* enable real irq */
- status = request_irq(pdata->irq, pcf857x_irq_demux, 0,
- dev_name(dev), gpio);
+ status = request_irq(client->irq, pcf857x_irq_demux, 0,
+ dev_name(&client->dev), gpio);
if (status)
goto fail;
/* enable gpio_to_irq() */
INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
gpio->chip.to_irq = pcf857x_to_irq;
- gpio->irq = pdata->irq;
+ gpio->irq = client->irq;
return 0;
@@ -285,8 +285,8 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->chip.ngpio = id->driver_data;
/* enable gpio_to_irq() if platform has settings */
- if (pdata && pdata->irq) {
- status = pcf857x_irq_domain_init(gpio, pdata, &client->dev);
+ if (pdata && client->irq) {
+ status = pcf857x_irq_domain_init(gpio, pdata, client);
if (status < 0) {
dev_err(&client->dev, "irq_domain init failed\n");
goto fail;
@@ -368,15 +368,6 @@ static int pcf857x_probe(struct i2c_client *client,
if (status < 0)
goto fail;
- /* NOTE: these chips can issue "some pin-changed" IRQs, which we
- * don't yet even try to use. Among other issues, the relevant
- * genirq state isn't available to modular drivers; and most irq
- * methods can't be called from sleeping contexts.
- */
-
- dev_info(&client->dev, "%s\n",
- client->irq ? " (irq ignored)" : "");
-
/* Let platform code set up the GPIOs and their users.
* Now is the first time anyone could use them.
*/
@@ -388,13 +379,15 @@ static int pcf857x_probe(struct i2c_client *client,
dev_warn(&client->dev, "setup --> %d\n", status);
}
+ dev_info(&client->dev, "probed\n");
+
return 0;
fail:
dev_dbg(&client->dev, "probe error %d for '%s'\n",
status, client->name);
- if (pdata && pdata->irq)
+ if (pdata && client->irq)
pcf857x_irq_domain_cleanup(gpio);
kfree(gpio);
@@ -418,7 +411,7 @@ static int pcf857x_remove(struct i2c_client *client)
}
}
- if (pdata && pdata->irq)
+ if (pdata && client->irq)
pcf857x_irq_domain_cleanup(gpio);
status = gpiochip_remove(&gpio->chip);
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 4ad0c4f9171c..cdf599687cf7 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -215,6 +215,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
struct gpio_chip *gpio = &chip->gpio;
gpio->label = dev_name(chip->dev);
+ gpio->dev = chip->dev;
gpio->owner = THIS_MODULE;
gpio->direction_input = pch_gpio_direction_input;
gpio->get = pch_gpio_get;
@@ -325,7 +326,7 @@ static irqreturn_t pch_gpio_handler(int irq, void *dev_id)
return ret;
}
-static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
+static void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
unsigned int irq_start, unsigned int num)
{
struct irq_chip_generic *gc;
@@ -345,7 +346,7 @@ static __devinit void pch_gpio_alloc_generic_chip(struct pch_gpio *chip,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
}
-static int __devinit pch_gpio_probe(struct pci_dev *pdev,
+static int pch_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
s32 ret;
@@ -442,7 +443,7 @@ err_pci_enable:
return ret;
}
-static void __devexit pch_gpio_remove(struct pci_dev *pdev)
+static void pch_gpio_remove(struct pci_dev *pdev)
{
int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
@@ -531,7 +532,7 @@ static struct pci_driver pch_gpio_driver = {
.name = "pch_gpio",
.id_table = pch_gpio_pcidev_id,
.probe = pch_gpio_probe,
- .remove = __devexit_p(pch_gpio_remove),
+ .remove = pch_gpio_remove,
.suspend = pch_gpio_suspend,
.resume = pch_gpio_resume
};
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b4b5da4fd2cc..c1720de18a4f 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -48,12 +48,7 @@ struct pl061_context_save_regs {
#endif
struct pl061_gpio {
- /* Each of the two spinlocks protects a different set of hardware
- * regiters and data structurs. This decouples the code of the IRQ from
- * the GPIO code. This also makes the case of a GPIO routine call from
- * the IRQ code simpler.
- */
- spinlock_t lock; /* GPIO registers */
+ spinlock_t lock;
void __iomem *base;
int irq_base;
@@ -216,39 +211,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
}
-static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
- struct pl061_platform_data *pdata;
+ struct device *dev = &adev->dev;
+ struct pl061_platform_data *pdata = dev->platform_data;
struct pl061_gpio *chip;
int ret, irq, i;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
- pdata = dev->dev.platform_data;
if (pdata) {
chip->gc.base = pdata->gpio_base;
chip->irq_base = pdata->irq_base;
- } else if (dev->dev.of_node) {
+ } else if (adev->dev.of_node) {
chip->gc.base = -1;
chip->irq_base = 0;
- } else {
- ret = -ENODEV;
- goto free_mem;
- }
+ } else
+ return -ENODEV;
- if (!request_mem_region(dev->res.start,
- resource_size(&dev->res), "pl061")) {
- ret = -EBUSY;
- goto free_mem;
- }
+ if (!devm_request_mem_region(dev, adev->res.start,
+ resource_size(&adev->res), "pl061"))
+ return -EBUSY;
- chip->base = ioremap(dev->res.start, resource_size(&dev->res));
- if (chip->base == NULL) {
- ret = -ENOMEM;
- goto release_region;
- }
+ chip->base = devm_ioremap(dev, adev->res.start,
+ resource_size(&adev->res));
+ if (chip->base == NULL)
+ return -ENOMEM;
spin_lock_init(&chip->lock);
@@ -258,13 +248,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
chip->gc.set = pl061_set_value;
chip->gc.to_irq = pl061_to_irq;
chip->gc.ngpio = PL061_GPIO_NR;
- chip->gc.label = dev_name(&dev->dev);
- chip->gc.dev = &dev->dev;
+ chip->gc.label = dev_name(dev);
+ chip->gc.dev = dev;
chip->gc.owner = THIS_MODULE;
ret = gpiochip_add(&chip->gc);
if (ret)
- goto iounmap;
+ return ret;
/*
* irq_chip support
@@ -276,11 +266,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
pl061_init_gc(chip, chip->irq_base);
writeb(0, chip->base + GPIOIE); /* disable irqs */
- irq = dev->irq[0];
- if (irq < 0) {
- ret = -ENODEV;
- goto iounmap;
- }
+ irq = adev->irq[0];
+ if (irq < 0)
+ return -ENODEV;
+
irq_set_chained_handler(irq, pl061_irq_handler);
irq_set_handler_data(irq, chip);
@@ -294,18 +283,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
}
}
- amba_set_drvdata(dev, chip);
+ amba_set_drvdata(adev, chip);
return 0;
-
-iounmap:
- iounmap(chip->base);
-release_region:
- release_mem_region(dev->res.start, resource_size(&dev->res));
-free_mem:
- kfree(chip);
-
- return ret;
}
#ifdef CONFIG_PM
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 98d52cb3fd1a..3e35243c136f 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -250,7 +250,7 @@ static int pxa_gpio_of_xlate(struct gpio_chip *gc,
}
#endif
-static int __devinit pxa_init_gpio_chip(int gpio_end,
+static int pxa_init_gpio_chip(int gpio_end,
int (*set_wake)(unsigned int, unsigned int))
{
int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
@@ -490,7 +490,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
};
-static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
+static int pxa_gpio_probe_dt(struct platform_device *pdev)
{
int ret, nr_banks, nr_gpios;
struct device_node *prev, *next, *np = pdev->dev.of_node;
@@ -537,7 +537,7 @@ err:
#define pxa_gpio_probe_dt(pdev) (-1)
#endif
-static int __devinit pxa_gpio_probe(struct platform_device *pdev)
+static int pxa_gpio_probe(struct platform_device *pdev)
{
struct pxa_gpio_chip *c;
struct resource *res;
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
index 08428bf17718..e63d6a397e17 100644
--- a/drivers/gpio/gpio-rc5t583.c
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -111,7 +111,7 @@ static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
}
-static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
+static int rc5t583_gpio_probe(struct platform_device *pdev)
{
struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -146,7 +146,7 @@ static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
return gpiochip_add(&rc5t583_gpio->gpio_chip);
}
-static int __devexit rc5t583_gpio_remove(struct platform_device *pdev)
+static int rc5t583_gpio_remove(struct platform_device *pdev)
{
struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
@@ -159,7 +159,7 @@ static struct platform_driver rc5t583_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = rc5t583_gpio_probe,
- .remove = __devexit_p(rc5t583_gpio_remove),
+ .remove = rc5t583_gpio_remove,
};
static int __init rc5t583_gpio_init(void)
diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c
index b62d443e9a59..1bf55f67f7a5 100644
--- a/drivers/gpio/gpio-rdc321x.c
+++ b/drivers/gpio/gpio-rdc321x.c
@@ -128,7 +128,7 @@ static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
/*
* Cache the initial value of both GPIO data registers
*/
-static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
+static int rdc321x_gpio_probe(struct platform_device *pdev)
{
int err;
struct resource *r;
@@ -206,7 +206,7 @@ out_free:
return err;
}
-static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
+static int rdc321x_gpio_remove(struct platform_device *pdev)
{
int ret;
struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
@@ -225,7 +225,7 @@ static struct platform_driver rdc321x_gpio_driver = {
.driver.name = "rdc321x-gpio",
.driver.owner = THIS_MODULE,
.probe = rdc321x_gpio_probe,
- .remove = __devexit_p(rdc321x_gpio_remove),
+ .remove = rdc321x_gpio_remove,
};
module_platform_driver(rdc321x_gpio_driver);
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 8707d4572a06..edae963f4625 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -185,7 +185,7 @@ static struct gpio_chip sch_gpio_resume = {
.set = sch_gpio_resume_set,
};
-static int __devinit sch_gpio_probe(struct platform_device *pdev)
+static int sch_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
int err, id;
@@ -271,7 +271,7 @@ err_sch_gpio_core:
return err;
}
-static int __devexit sch_gpio_remove(struct platform_device *pdev)
+static int sch_gpio_remove(struct platform_device *pdev)
{
struct resource *res;
if (gpio_ba) {
@@ -303,7 +303,7 @@ static struct platform_driver sch_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = sch_gpio_probe,
- .remove = __devexit_p(sch_gpio_remove),
+ .remove = sch_gpio_remove,
};
module_platform_driver(sch_gpio_driver);
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index e25f73130b40..88f374ac7753 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -129,7 +129,7 @@ static struct irq_domain_ops irq_domain_sdv_ops = {
.xlate = sdv_xlate,
};
-static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
+static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
struct pci_dev *pdev)
{
struct irq_chip_type *ct;
@@ -186,7 +186,7 @@ out_free_desc:
return ret;
}
-static int __devinit sdv_gpio_probe(struct pci_dev *pdev,
+static int sdv_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
struct sdv_gpio_chip_data *sd;
diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c
new file mode 100644
index 000000000000..5f45fc4ed5d1
--- /dev/null
+++ b/drivers/gpio/gpio-spear-spics.c
@@ -0,0 +1,217 @@
+/*
+ * SPEAr platform SPI chipselect abstraction over gpiolib
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@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/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/* maximum chipselects */
+#define NUM_OF_GPIO 4
+
+/*
+ * Provision is available on some SPEAr SoCs to control ARM PL022 spi cs
+ * through system registers. This register lies outside spi (pl022)
+ * address space into system registers.
+ *
+ * It provides control for spi chip select lines so that any chipselect
+ * (out of 4 possible chipselects in pl022) can be made low to select
+ * the particular slave.
+ */
+
+/**
+ * struct spear_spics - represents spi chip select control
+ * @base: base address
+ * @perip_cfg: configuration register
+ * @sw_enable_bit: bit to enable s/w control over chipselects
+ * @cs_value_bit: bit to program high or low chipselect
+ * @cs_enable_mask: mask to select bits required to select chipselect
+ * @cs_enable_shift: bit pos of cs_enable_mask
+ * @use_count: use count of a spi controller cs lines
+ * @last_off: stores last offset caller of set_value()
+ * @chip: gpio_chip abstraction
+ */
+struct spear_spics {
+ void __iomem *base;
+ u32 perip_cfg;
+ u32 sw_enable_bit;
+ u32 cs_value_bit;
+ u32 cs_enable_mask;
+ u32 cs_enable_shift;
+ unsigned long use_count;
+ int last_off;
+ struct gpio_chip chip;
+};
+
+/* gpio framework specific routines */
+static int spics_get_value(struct gpio_chip *chip, unsigned offset)
+{
+ return -ENXIO;
+}
+
+static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ /* select chip select from register */
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ if (spics->last_off != offset) {
+ spics->last_off = offset;
+ tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift);
+ tmp |= offset << spics->cs_enable_shift;
+ }
+
+ /* toggle chip select line */
+ tmp &= ~(0x1 << spics->cs_value_bit);
+ tmp |= value << spics->cs_value_bit;
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+}
+
+static int spics_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ return -ENXIO;
+}
+
+static int spics_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ spics_set_value(chip, offset, value);
+ return 0;
+}
+
+static int spics_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ if (!spics->use_count++) {
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ tmp |= 0x1 << spics->sw_enable_bit;
+ tmp |= 0x1 << spics->cs_value_bit;
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+ }
+
+ return 0;
+}
+
+static void spics_free(struct gpio_chip *chip, unsigned offset)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ if (!--spics->use_count) {
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ tmp &= ~(0x1 << spics->sw_enable_bit);
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+ }
+}
+
+static int spics_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct spear_spics *spics;
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+ return -EBUSY;
+ }
+
+ spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
+ if (!spics) {
+ dev_err(&pdev->dev, "memory allocation fail\n");
+ return -ENOMEM;
+ }
+
+ spics->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!spics->base) {
+ dev_err(&pdev->dev, "request and ioremap fail\n");
+ return -ENOMEM;
+ }
+
+ if (of_property_read_u32(np, "st-spics,peripcfg-reg",
+ &spics->perip_cfg))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,sw-enable-bit",
+ &spics->sw_enable_bit))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-value-bit",
+ &spics->cs_value_bit))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-enable-mask",
+ &spics->cs_enable_mask))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-enable-shift",
+ &spics->cs_enable_shift))
+ goto err_dt_data;
+
+ platform_set_drvdata(pdev, spics);
+
+ spics->chip.ngpio = NUM_OF_GPIO;
+ spics->chip.base = -1;
+ spics->chip.request = spics_request;
+ spics->chip.free = spics_free;
+ spics->chip.direction_input = spics_direction_input;
+ spics->chip.direction_output = spics_direction_output;
+ spics->chip.get = spics_get_value;
+ spics->chip.set = spics_set_value;
+ spics->chip.label = dev_name(&pdev->dev);
+ spics->chip.dev = &pdev->dev;
+ spics->chip.owner = THIS_MODULE;
+ spics->last_off = -1;
+
+ ret = gpiochip_add(&spics->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to add gpio chip\n");
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "spear spics registered\n");
+ return 0;
+
+err_dt_data:
+ dev_err(&pdev->dev, "DT probe failed\n");
+ return -EINVAL;
+}
+
+static const struct of_device_id spics_gpio_of_match[] = {
+ { .compatible = "st,spear-spics-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
+
+static struct platform_driver spics_gpio_driver = {
+ .probe = spics_gpio_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "spear-spics-gpio",
+ .of_match_table = spics_gpio_of_match,
+ },
+};
+
+static int __init spics_gpio_init(void)
+{
+ return platform_driver_register(&spics_gpio_driver);
+}
+subsys_initcall(spics_gpio_init);
+
+MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
index 6064fb376e11..558542552aae 100644
--- a/drivers/gpio/gpio-sta2x11.c
+++ b/drivers/gpio/gpio-sta2x11.c
@@ -320,7 +320,7 @@ static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
return ret;
}
-static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
+static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
@@ -353,7 +353,7 @@ static __devinit void gsta_alloc_irq_chip(struct gsta_gpio *chip)
}
/* The platform device used here is instantiated by the MFD device */
-static int __devinit gsta_probe(struct platform_device *dev)
+static int gsta_probe(struct platform_device *dev)
{
int i, err;
struct pci_dev *pdev;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index dce34727bbf8..770476a9da87 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -11,7 +11,9 @@
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <linux/mfd/stmpe.h>
/*
@@ -28,6 +30,7 @@ struct stmpe_gpio {
struct stmpe *stmpe;
struct device *dev;
struct mutex irq_lock;
+ struct irq_domain *domain;
int irq_base;
unsigned norequest_mask;
@@ -103,7 +106,7 @@ static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
- return stmpe_gpio->irq_base + offset;
+ return irq_create_mapping(stmpe_gpio->domain, offset);
}
static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -132,7 +135,7 @@ static struct gpio_chip template_chip = {
static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
- int offset = d->irq - stmpe_gpio->irq_base;
+ int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -199,7 +202,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
static void stmpe_gpio_irq_mask(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
- int offset = d->irq - stmpe_gpio->irq_base;
+ int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -209,7 +212,7 @@ static void stmpe_gpio_irq_mask(struct irq_data *d)
static void stmpe_gpio_irq_unmask(struct irq_data *d)
{
struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d);
- int offset = d->irq - stmpe_gpio->irq_base;
+ int offset = d->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -251,8 +254,9 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
while (stat) {
int bit = __ffs(stat);
int line = bank * 8 + bit;
+ int virq = irq_find_mapping(stmpe_gpio->domain, line);
- handle_nested_irq(stmpe_gpio->irq_base + line);
+ handle_nested_irq(virq);
stat &= ~(1 << bit);
}
@@ -267,43 +271,61 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-static int __devinit stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hwirq)
{
- int base = stmpe_gpio->irq_base;
- int irq;
+ struct stmpe_gpio *stmpe_gpio = d->host_data;
+
+ if (!stmpe_gpio)
+ return -EINVAL;
- for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
- irq_set_chip_data(irq, stmpe_gpio);
- irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
- handle_simple_irq);
- irq_set_nested_thread(irq, 1);
+ irq_set_chip_data(hwirq, stmpe_gpio);
+ irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip,
+ handle_simple_irq);
+ irq_set_nested_thread(hwirq, 1);
#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
+ set_irq_flags(hwirq, IRQF_VALID);
#else
- irq_set_noprobe(irq);
+ irq_set_noprobe(hwirq);
#endif
- }
return 0;
}
-static void stmpe_gpio_irq_remove(struct stmpe_gpio *stmpe_gpio)
+void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
{
- int base = stmpe_gpio->irq_base;
- int irq;
-
- for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
#ifdef CONFIG_ARM
- set_irq_flags(irq, 0);
+ set_irq_flags(virq, 0);
#endif
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
+ irq_set_chip_and_handler(virq, NULL, NULL);
+ irq_set_chip_data(virq, NULL);
+}
+
+static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
+ .unmap = stmpe_gpio_irq_unmap,
+ .map = stmpe_gpio_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+{
+ int base = stmpe_gpio->irq_base;
+
+ stmpe_gpio->domain = irq_domain_add_simple(NULL,
+ stmpe_gpio->chip.ngpio, base,
+ &stmpe_gpio_irq_simple_ops, stmpe_gpio);
+ if (!stmpe_gpio->domain) {
+ dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
+ return -ENOSYS;
}
+
+ return 0;
}
-static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
+static int stmpe_gpio_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *np = pdev->dev.of_node;
struct stmpe_gpio_platform_data *pdata;
struct stmpe_gpio *stmpe_gpio;
int ret;
@@ -321,13 +343,17 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
stmpe_gpio->dev = &pdev->dev;
stmpe_gpio->stmpe = stmpe;
- stmpe_gpio->norequest_mask = pdata ? pdata->norequest_mask : 0;
-
stmpe_gpio->chip = template_chip;
stmpe_gpio->chip.ngpio = stmpe->num_gpios;
stmpe_gpio->chip.dev = &pdev->dev;
stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
+ if (pdata)
+ stmpe_gpio->norequest_mask = pdata->norequest_mask;
+ else if (np)
+ of_property_read_u32(np, "st,norequest-mask",
+ &stmpe_gpio->norequest_mask);
+
if (irq >= 0)
stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
else
@@ -348,7 +374,7 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
IRQF_ONESHOT, "stmpe-gpio", stmpe_gpio);
if (ret) {
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
- goto out_removeirq;
+ goto out_disable;
}
}
@@ -368,9 +394,6 @@ static int __devinit stmpe_gpio_probe(struct platform_device *pdev)
out_freeirq:
if (irq >= 0)
free_irq(irq, stmpe_gpio);
-out_removeirq:
- if (irq >= 0)
- stmpe_gpio_irq_remove(stmpe_gpio);
out_disable:
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
out_free:
@@ -378,7 +401,7 @@ out_free:
return ret;
}
-static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
+static int stmpe_gpio_remove(struct platform_device *pdev)
{
struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
struct stmpe *stmpe = stmpe_gpio->stmpe;
@@ -398,10 +421,9 @@ static int __devexit stmpe_gpio_remove(struct platform_device *pdev)
stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
- if (irq >= 0) {
+ if (irq >= 0)
free_irq(irq, stmpe_gpio);
- stmpe_gpio_irq_remove(stmpe_gpio);
- }
+
platform_set_drvdata(pdev, NULL);
kfree(stmpe_gpio);
@@ -412,7 +434,7 @@ static struct platform_driver stmpe_gpio_driver = {
.driver.name = "stmpe-gpio",
.driver.owner = THIS_MODULE,
.probe = stmpe_gpio_probe,
- .remove = __devexit_p(stmpe_gpio_remove),
+ .remove = stmpe_gpio_remove,
};
static int __init stmpe_gpio_init(void)
diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c
index 8bead0bb6459..85841ee70b17 100644
--- a/drivers/gpio/gpio-stp-xway.c
+++ b/drivers/gpio/gpio-stp-xway.c
@@ -197,7 +197,7 @@ static int xway_stp_hw_init(struct xway_stp *chip)
return 0;
}
-static int __devinit xway_stp_probe(struct platform_device *pdev)
+static int xway_stp_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
const __be32 *shadow, *groups, *dsl, *phy;
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index eb3e215d2396..796b6c42fa70 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -575,7 +575,7 @@ static void sx150x_remove_irq_chip(struct sx150x_chip *chip)
}
}
-static int __devinit sx150x_probe(struct i2c_client *client,
+static int sx150x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
@@ -622,7 +622,7 @@ probe_fail_pre_gpiochip_add:
return rc;
}
-static int __devexit sx150x_remove(struct i2c_client *client)
+static int sx150x_remove(struct i2c_client *client)
{
struct sx150x_chip *chip;
int rc;
@@ -646,7 +646,7 @@ static struct i2c_driver sx150x_driver = {
.owner = THIS_MODULE
},
.probe = sx150x_probe,
- .remove = __devexit_p(sx150x_remove),
+ .remove = sx150x_remove,
.id_table = sx150x_id,
};
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 1e48317e70fb..c0595bbf3268 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
{
int base = tc3589x_gpio->irq_base;
- if (base) {
- tc3589x_gpio->domain = irq_domain_add_legacy(
- NULL, tc3589x_gpio->chip.ngpio, base,
- 0, &tc3589x_irq_ops, tc3589x_gpio);
- }
- else {
- tc3589x_gpio->domain = irq_domain_add_linear(
- np, tc3589x_gpio->chip.ngpio,
- &tc3589x_irq_ops, tc3589x_gpio);
- }
-
+ /*
+ * If this results in a linear domain, irq_create_mapping() will
+ * take care of allocating IRQ descriptors at runtime. When a base
+ * is provided, the IRQ descriptors will be allocated when the
+ * domain is instantiated.
+ */
+ tc3589x_gpio->domain = irq_domain_add_simple(np,
+ tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
+ tc3589x_gpio);
if (!tc3589x_gpio->domain) {
dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
return -ENOSYS;
@@ -311,7 +309,7 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
return 0;
}
-static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
+static int tc3589x_gpio_probe(struct platform_device *pdev)
{
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
struct tc3589x_gpio_platform_data *pdata;
@@ -389,7 +387,7 @@ out_free:
return ret;
}
-static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
+static int tc3589x_gpio_remove(struct platform_device *pdev)
{
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
@@ -419,7 +417,7 @@ static struct platform_driver tc3589x_gpio_driver = {
.driver.name = "tc3589x-gpio",
.driver.owner = THIS_MODULE,
.probe = tc3589x_gpio_probe,
- .remove = __devexit_p(tc3589x_gpio_remove),
+ .remove = tc3589x_gpio_remove,
};
static int __init tc3589x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index d982593d7563..63cb643d4b5a 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/irqdomain.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pm.h>
#include <asm/mach/irq.h>
@@ -64,7 +65,7 @@ struct tegra_gpio_bank {
int bank;
int irq;
spinlock_t lvl_lock[4];
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
u32 cnf[4];
u32 out[4];
u32 oe[4];
@@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio)
{
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
}
-EXPORT_SYMBOL_GPL(tegra_gpio_enable);
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)
+static 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)
+static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
{
pinctrl_free_gpio(offset);
tegra_gpio_disable(offset);
@@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
{
+ /* If gpio is in output mode then read from the out value */
+ if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1)
+ return (tegra_gpio_readl(GPIO_OUT(offset)) >>
+ GPIO_BIT(offset)) & 0x1;
+
return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
}
@@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
}
-#ifdef CONFIG_PM
-void tegra_gpio_resume(void)
+#ifdef CONFIG_PM_SLEEP
+static int tegra_gpio_resume(struct device *dev)
{
unsigned long flags;
int b;
@@ -308,9 +312,10 @@ void tegra_gpio_resume(void)
}
local_irq_restore(flags);
+ return 0;
}
-void tegra_gpio_suspend(void)
+static int tegra_gpio_suspend(struct device *dev)
{
unsigned long flags;
int b;
@@ -330,6 +335,7 @@ void tegra_gpio_suspend(void)
}
}
local_irq_restore(flags);
+ return 0;
}
static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
@@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = {
.irq_mask = tegra_gpio_irq_mask,
.irq_unmask = tegra_gpio_irq_unmask,
.irq_set_type = tegra_gpio_irq_set_type,
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
.irq_set_wake = tegra_gpio_wake_enable,
#endif
};
+static const struct dev_pm_ops tegra_gpio_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
+};
+
struct tegra_gpio_soc_config {
u32 bank_stride;
u32 upper_offset;
@@ -365,7 +375,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
.upper_offset = 0x80,
};
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+static struct of_device_id tegra_gpio_of_match[] = {
{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
{ },
@@ -376,11 +386,10 @@ static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
*/
static struct lock_class_key gpio_lock_class;
-static int __devinit tegra_gpio_probe(struct platform_device *pdev)
+static int tegra_gpio_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct tegra_gpio_soc_config *config;
- int irq_base;
struct resource *res;
struct tegra_gpio_bank *bank;
int gpio;
@@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
- irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0);
- if (irq_base < 0) {
- dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
- return -ENODEV;
- }
- irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
- tegra_gpio_chip.ngpio, irq_base, 0,
+ irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+ tegra_gpio_chip.ngpio,
&irq_domain_simple_ops, NULL);
+ if (!irq_domain)
+ return -ENODEV;
for (i = 0; i < tegra_gpio_bank_count; i++) {
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
@@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
gpiochip_add(&tegra_gpio_chip);
for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
- int irq = irq_find_mapping(irq_domain, gpio);
+ int irq = irq_create_mapping(irq_domain, gpio);
/* No validity check; all Tegra GPIOs are valid IRQs */
bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
@@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = {
.driver = {
.name = "tegra-gpio",
.owner = THIS_MODULE,
+ .pm = &tegra_gpio_pm_ops,
.of_match_table = tegra_gpio_of_match,
},
.probe = tegra_gpio_probe,
diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c
index 1a3e2b9b4772..702cca9284f1 100644
--- a/drivers/gpio/gpio-timberdale.c
+++ b/drivers/gpio/gpio-timberdale.c
@@ -222,7 +222,7 @@ static struct irq_chip timbgpio_irqchip = {
.irq_set_type = timbgpio_irq_type,
};
-static int __devinit timbgpio_probe(struct platform_device *pdev)
+static int timbgpio_probe(struct platform_device *pdev)
{
int err, i;
struct gpio_chip *gc;
@@ -316,7 +316,7 @@ err_mem:
return err;
}
-static int __devexit timbgpio_remove(struct platform_device *pdev)
+static int timbgpio_remove(struct platform_device *pdev)
{
int err;
struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c
index 2526b3bb0fae..c1b82da56504 100644
--- a/drivers/gpio/gpio-tps6586x.c
+++ b/drivers/gpio/gpio-tps6586x.c
@@ -80,7 +80,7 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
val, mask);
}
-static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
+static int tps6586x_gpio_probe(struct platform_device *pdev)
{
struct tps6586x_platform_data *pdata;
struct tps6586x_gpio *tps6586x_gpio;
@@ -126,7 +126,7 @@ static int __devinit tps6586x_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit tps6586x_gpio_remove(struct platform_device *pdev)
+static int tps6586x_gpio_remove(struct platform_device *pdev)
{
struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev);
@@ -137,7 +137,7 @@ static struct platform_driver tps6586x_gpio_driver = {
.driver.name = "tps6586x-gpio",
.driver.owner = THIS_MODULE,
.probe = tps6586x_gpio_probe,
- .remove = __devexit_p(tps6586x_gpio_remove),
+ .remove = tps6586x_gpio_remove,
};
static int __init tps6586x_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 11f29c82253c..5083825a0348 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -113,7 +113,7 @@ static struct tps65910_board *tps65910_parse_dt_for_gpio(struct device *dev,
}
#endif
-static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
+static int tps65910_gpio_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
@@ -188,7 +188,7 @@ skip_init:
return ret;
}
-static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
+static int tps65910_gpio_remove(struct platform_device *pdev)
{
struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
@@ -199,7 +199,7 @@ static struct platform_driver tps65910_gpio_driver = {
.driver.name = "tps65910-gpio",
.driver.owner = THIS_MODULE,
.probe = tps65910_gpio_probe,
- .remove = __devexit_p(tps65910_gpio_remove),
+ .remove = tps65910_gpio_remove,
};
static int __init tps65910_gpio_init(void)
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index 99106d1e2e55..30a5844a7dca 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -84,7 +84,7 @@ static struct gpio_chip template_chip = {
.base = -1,
};
-static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
+static int tps65912_gpio_probe(struct platform_device *pdev)
{
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
struct tps65912_board *pdata = tps65912->dev->platform_data;
@@ -113,7 +113,7 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
+static int tps65912_gpio_remove(struct platform_device *pdev)
{
struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev);
@@ -126,7 +126,7 @@ static struct platform_driver tps65912_gpio_driver = {
.owner = THIS_MODULE,
},
.probe = tps65912_gpio_probe,
- .remove = __devexit_p(tps65912_gpio_remove),
+ .remove = tps65912_gpio_remove,
};
static int __init tps65912_gpio_init(void)
diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c
new file mode 100644
index 000000000000..0634ceea3c24
--- /dev/null
+++ b/drivers/gpio/gpio-ts5500.c
@@ -0,0 +1,466 @@
+/*
+ * Digital I/O driver for Technologic Systems TS-5500
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * Technologic Systems platforms have pin blocks, exposing several Digital
+ * Input/Output lines (DIO). This driver aims to support single pin blocks.
+ * In that sense, the support is not limited to the TS-5500 blocks.
+ * Actually, the following platforms have DIO support:
+ *
+ * TS-5500:
+ * Documentation: http://wiki.embeddedarm.com/wiki/TS-5500
+ * Blocks: DIO1, DIO2 and LCD port.
+ *
+ * TS-5600:
+ * Documentation: http://wiki.embeddedarm.com/wiki/TS-5600
+ * Blocks: LCD port (identical to TS-5500 LCD).
+ *
+ * This program is free software; you can 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/bitops.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_data/gpio-ts5500.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* List of supported Technologic Systems platforms DIO blocks */
+enum ts5500_blocks { TS5500_DIO1, TS5500_DIO2, TS5500_LCD, TS5600_LCD };
+
+struct ts5500_priv {
+ const struct ts5500_dio *pinout;
+ struct gpio_chip gpio_chip;
+ spinlock_t lock;
+ bool strap;
+ u8 hwirq;
+};
+
+/*
+ * Hex 7D is used to control several blocks (e.g. DIO2 and LCD port).
+ * This flag ensures that the region has been requested by this driver.
+ */
+static bool hex7d_reserved;
+
+/*
+ * This structure is used to describe capabilities of DIO lines,
+ * such as available directions and connected interrupt (if any).
+ */
+struct ts5500_dio {
+ const u8 value_addr;
+ const u8 value_mask;
+ const u8 control_addr;
+ const u8 control_mask;
+ const bool no_input;
+ const bool no_output;
+ const u8 irq;
+};
+
+#define TS5500_DIO_IN_OUT(vaddr, vbit, caddr, cbit) \
+ { \
+ .value_addr = vaddr, \
+ .value_mask = BIT(vbit), \
+ .control_addr = caddr, \
+ .control_mask = BIT(cbit), \
+ }
+
+#define TS5500_DIO_IN(addr, bit) \
+ { \
+ .value_addr = addr, \
+ .value_mask = BIT(bit), \
+ .no_output = true, \
+ }
+
+#define TS5500_DIO_IN_IRQ(addr, bit, _irq) \
+ { \
+ .value_addr = addr, \
+ .value_mask = BIT(bit), \
+ .no_output = true, \
+ .irq = _irq, \
+ }
+
+#define TS5500_DIO_OUT(addr, bit) \
+ { \
+ .value_addr = addr, \
+ .value_mask = BIT(bit), \
+ .no_input = true, \
+ }
+
+/*
+ * Input/Output DIO lines are programmed in groups of 4. Their values are
+ * available through 4 consecutive bits in a value port, whereas the direction
+ * of these 4 lines is driven by only 1 bit in a control port.
+ */
+#define TS5500_DIO_GROUP(vaddr, vbitfrom, caddr, cbit) \
+ TS5500_DIO_IN_OUT(vaddr, vbitfrom + 0, caddr, cbit), \
+ TS5500_DIO_IN_OUT(vaddr, vbitfrom + 1, caddr, cbit), \
+ TS5500_DIO_IN_OUT(vaddr, vbitfrom + 2, caddr, cbit), \
+ TS5500_DIO_IN_OUT(vaddr, vbitfrom + 3, caddr, cbit)
+
+/*
+ * TS-5500 DIO1 block
+ *
+ * value control dir hw
+ * addr bit addr bit in out irq name pin offset
+ *
+ * 0x7b 0 0x7a 0 x x DIO1_0 1 0
+ * 0x7b 1 0x7a 0 x x DIO1_1 3 1
+ * 0x7b 2 0x7a 0 x x DIO1_2 5 2
+ * 0x7b 3 0x7a 0 x x DIO1_3 7 3
+ * 0x7b 4 0x7a 1 x x DIO1_4 9 4
+ * 0x7b 5 0x7a 1 x x DIO1_5 11 5
+ * 0x7b 6 0x7a 1 x x DIO1_6 13 6
+ * 0x7b 7 0x7a 1 x x DIO1_7 15 7
+ * 0x7c 0 0x7a 5 x x DIO1_8 4 8
+ * 0x7c 1 0x7a 5 x x DIO1_9 6 9
+ * 0x7c 2 0x7a 5 x x DIO1_10 8 10
+ * 0x7c 3 0x7a 5 x x DIO1_11 10 11
+ * 0x7c 4 x DIO1_12 12 12
+ * 0x7c 5 x 7 DIO1_13 14 13
+ */
+static const struct ts5500_dio ts5500_dio1[] = {
+ TS5500_DIO_GROUP(0x7b, 0, 0x7a, 0),
+ TS5500_DIO_GROUP(0x7b, 4, 0x7a, 1),
+ TS5500_DIO_GROUP(0x7c, 0, 0x7a, 5),
+ TS5500_DIO_IN(0x7c, 4),
+ TS5500_DIO_IN_IRQ(0x7c, 5, 7),
+};
+
+/*
+ * TS-5500 DIO2 block
+ *
+ * value control dir hw
+ * addr bit addr bit in out irq name pin offset
+ *
+ * 0x7e 0 0x7d 0 x x DIO2_0 1 0
+ * 0x7e 1 0x7d 0 x x DIO2_1 3 1
+ * 0x7e 2 0x7d 0 x x DIO2_2 5 2
+ * 0x7e 3 0x7d 0 x x DIO2_3 7 3
+ * 0x7e 4 0x7d 1 x x DIO2_4 9 4
+ * 0x7e 5 0x7d 1 x x DIO2_5 11 5
+ * 0x7e 6 0x7d 1 x x DIO2_6 13 6
+ * 0x7e 7 0x7d 1 x x DIO2_7 15 7
+ * 0x7f 0 0x7d 5 x x DIO2_8 4 8
+ * 0x7f 1 0x7d 5 x x DIO2_9 6 9
+ * 0x7f 2 0x7d 5 x x DIO2_10 8 10
+ * 0x7f 3 0x7d 5 x x DIO2_11 10 11
+ * 0x7f 4 x 6 DIO2_13 14 12
+ */
+static const struct ts5500_dio ts5500_dio2[] = {
+ TS5500_DIO_GROUP(0x7e, 0, 0x7d, 0),
+ TS5500_DIO_GROUP(0x7e, 4, 0x7d, 1),
+ TS5500_DIO_GROUP(0x7f, 0, 0x7d, 5),
+ TS5500_DIO_IN_IRQ(0x7f, 4, 6),
+};
+
+/*
+ * TS-5500 LCD port used as DIO block
+ * TS-5600 LCD port is identical
+ *
+ * value control dir hw
+ * addr bit addr bit in out irq name pin offset
+ *
+ * 0x72 0 0x7d 2 x x LCD_0 8 0
+ * 0x72 1 0x7d 2 x x LCD_1 7 1
+ * 0x72 2 0x7d 2 x x LCD_2 10 2
+ * 0x72 3 0x7d 2 x x LCD_3 9 3
+ * 0x72 4 0x7d 3 x x LCD_4 12 4
+ * 0x72 5 0x7d 3 x x LCD_5 11 5
+ * 0x72 6 0x7d 3 x x LCD_6 14 6
+ * 0x72 7 0x7d 3 x x LCD_7 13 7
+ * 0x73 0 x LCD_EN 5 8
+ * 0x73 6 x LCD_WR 6 9
+ * 0x73 7 x 1 LCD_RS 3 10
+ */
+static const struct ts5500_dio ts5500_lcd[] = {
+ TS5500_DIO_GROUP(0x72, 0, 0x7d, 2),
+ TS5500_DIO_GROUP(0x72, 4, 0x7d, 3),
+ TS5500_DIO_OUT(0x73, 0),
+ TS5500_DIO_IN(0x73, 6),
+ TS5500_DIO_IN_IRQ(0x73, 7, 1),
+};
+
+static inline struct ts5500_priv *ts5500_gc_to_priv(struct gpio_chip *chip)
+{
+ return container_of(chip, struct ts5500_priv, gpio_chip);
+}
+
+static inline void ts5500_set_mask(u8 mask, u8 addr)
+{
+ u8 val = inb(addr);
+ val |= mask;
+ outb(val, addr);
+}
+
+static inline void ts5500_clear_mask(u8 mask, u8 addr)
+{
+ u8 val = inb(addr);
+ val &= ~mask;
+ outb(val, addr);
+}
+
+static int ts5500_gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+ const struct ts5500_dio line = priv->pinout[offset];
+ unsigned long flags;
+
+ if (line.no_input)
+ return -ENXIO;
+
+ if (line.no_output)
+ return 0;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ts5500_clear_mask(line.control_mask, line.control_addr);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int ts5500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+ const struct ts5500_dio line = priv->pinout[offset];
+
+ return !!(inb(line.value_addr) & line.value_mask);
+}
+
+static int ts5500_gpio_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+ const struct ts5500_dio line = priv->pinout[offset];
+ unsigned long flags;
+
+ if (line.no_output)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!line.no_input)
+ ts5500_set_mask(line.control_mask, line.control_addr);
+
+ if (val)
+ ts5500_set_mask(line.value_mask, line.value_addr);
+ else
+ ts5500_clear_mask(line.value_mask, line.value_addr);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+ const struct ts5500_dio line = priv->pinout[offset];
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (val)
+ ts5500_set_mask(line.value_mask, line.value_addr);
+ else
+ ts5500_clear_mask(line.value_mask, line.value_addr);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int ts5500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct ts5500_priv *priv = ts5500_gc_to_priv(chip);
+ const struct ts5500_dio *block = priv->pinout;
+ const struct ts5500_dio line = block[offset];
+
+ /* Only one pin is connected to an interrupt */
+ if (line.irq)
+ return line.irq;
+
+ /* As this pin is input-only, we may strap it to another in/out pin */
+ if (priv->strap)
+ return priv->hwirq;
+
+ return -ENXIO;
+}
+
+static int ts5500_enable_irq(struct ts5500_priv *priv)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->hwirq == 7)
+ ts5500_set_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */
+ else if (priv->hwirq == 6)
+ ts5500_set_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */
+ else if (priv->hwirq == 1)
+ ts5500_set_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */
+ else
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
+}
+
+static void ts5500_disable_irq(struct ts5500_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->hwirq == 7)
+ ts5500_clear_mask(BIT(7), 0x7a); /* DIO1_13 on IRQ7 */
+ else if (priv->hwirq == 6)
+ ts5500_clear_mask(BIT(7), 0x7d); /* DIO2_13 on IRQ6 */
+ else if (priv->hwirq == 1)
+ ts5500_clear_mask(BIT(6), 0x7d); /* LCD_RS on IRQ1 */
+ else
+ dev_err(priv->gpio_chip.dev, "invalid hwirq %d\n", priv->hwirq);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int __devinit ts5500_dio_probe(struct platform_device *pdev)
+{
+ enum ts5500_blocks block = platform_get_device_id(pdev)->driver_data;
+ struct ts5500_dio_platform_data *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ const char *name = dev_name(dev);
+ struct ts5500_priv *priv;
+ struct resource *res;
+ unsigned long flags;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "missing IRQ resource\n");
+ return -EINVAL;
+ }
+
+ priv = devm_kzalloc(dev, sizeof(struct ts5500_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+ priv->hwirq = res->start;
+ spin_lock_init(&priv->lock);
+
+ priv->gpio_chip.owner = THIS_MODULE;
+ priv->gpio_chip.label = name;
+ priv->gpio_chip.dev = dev;
+ priv->gpio_chip.direction_input = ts5500_gpio_input;
+ priv->gpio_chip.direction_output = ts5500_gpio_output;
+ priv->gpio_chip.get = ts5500_gpio_get;
+ priv->gpio_chip.set = ts5500_gpio_set;
+ priv->gpio_chip.to_irq = ts5500_gpio_to_irq;
+ priv->gpio_chip.base = -1;
+ if (pdata) {
+ priv->gpio_chip.base = pdata->base;
+ priv->strap = pdata->strap;
+ }
+
+ switch (block) {
+ case TS5500_DIO1:
+ priv->pinout = ts5500_dio1;
+ priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio1);
+
+ if (!devm_request_region(dev, 0x7a, 3, name)) {
+ dev_err(dev, "failed to request %s ports\n", name);
+ return -EBUSY;
+ }
+ break;
+ case TS5500_DIO2:
+ priv->pinout = ts5500_dio2;
+ priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_dio2);
+
+ if (!devm_request_region(dev, 0x7e, 2, name)) {
+ dev_err(dev, "failed to request %s ports\n", name);
+ return -EBUSY;
+ }
+
+ if (hex7d_reserved)
+ break;
+
+ if (!devm_request_region(dev, 0x7d, 1, name)) {
+ dev_err(dev, "failed to request %s 7D\n", name);
+ return -EBUSY;
+ }
+
+ hex7d_reserved = true;
+ break;
+ case TS5500_LCD:
+ case TS5600_LCD:
+ priv->pinout = ts5500_lcd;
+ priv->gpio_chip.ngpio = ARRAY_SIZE(ts5500_lcd);
+
+ if (!devm_request_region(dev, 0x72, 2, name)) {
+ dev_err(dev, "failed to request %s ports\n", name);
+ return -EBUSY;
+ }
+
+ if (!hex7d_reserved) {
+ if (!devm_request_region(dev, 0x7d, 1, name)) {
+ dev_err(dev, "failed to request %s 7D\n", name);
+ return -EBUSY;
+ }
+
+ hex7d_reserved = true;
+ }
+
+ /* Ensure usage of LCD port as DIO */
+ spin_lock_irqsave(&priv->lock, flags);
+ ts5500_clear_mask(BIT(4), 0x7d);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ break;
+ }
+
+ ret = gpiochip_add(&priv->gpio_chip);
+ if (ret) {
+ dev_err(dev, "failed to register the gpio chip\n");
+ return ret;
+ }
+
+ ret = ts5500_enable_irq(priv);
+ if (ret) {
+ dev_err(dev, "invalid interrupt %d\n", priv->hwirq);
+ goto cleanup;
+ }
+
+ return 0;
+cleanup:
+ if (gpiochip_remove(&priv->gpio_chip))
+ dev_err(dev, "failed to remove gpio chip\n");
+ return ret;
+}
+
+static int __devexit ts5500_dio_remove(struct platform_device *pdev)
+{
+ struct ts5500_priv *priv = platform_get_drvdata(pdev);
+
+ ts5500_disable_irq(priv);
+ return gpiochip_remove(&priv->gpio_chip);
+}
+
+static struct platform_device_id ts5500_dio_ids[] = {
+ { "ts5500-dio1", TS5500_DIO1 },
+ { "ts5500-dio2", TS5500_DIO2 },
+ { "ts5500-dio-lcd", TS5500_LCD },
+ { "ts5600-dio-lcd", TS5600_LCD },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, ts5500_dio_ids);
+
+static struct platform_driver ts5500_dio_driver = {
+ .driver = {
+ .name = "ts5500-dio",
+ .owner = THIS_MODULE,
+ },
+ .probe = ts5500_dio_probe,
+ .remove = __devexit_p(ts5500_dio_remove),
+ .id_table = ts5500_dio_ids,
+};
+
+module_platform_driver(ts5500_dio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>");
+MODULE_DESCRIPTION("Technologic Systems TS-5500 Digital I/O driver");
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index c5f8ca233e1f..00329f2fc05b 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -88,11 +88,15 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
/*----------------------------------------------------------------------*/
/*
- * LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
+ * LED register offsets from TWL_MODULE_LED base
* PWMs A and B are dedicated to LEDs A and B, respectively.
*/
-#define TWL4030_LED_LEDEN 0x0
+#define TWL4030_LED_LEDEN_REG 0x00
+#define TWL4030_PWMAON_REG 0x01
+#define TWL4030_PWMAOFF_REG 0x02
+#define TWL4030_PWMBON_REG 0x03
+#define TWL4030_PWMBOFF_REG 0x04
/* LEDEN bits */
#define LEDEN_LEDAON BIT(0)
@@ -104,9 +108,6 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
#define LEDEN_PWM_LENGTHA BIT(6)
#define LEDEN_PWM_LENGTHB BIT(7)
-#define TWL4030_PWMx_PWMxON 0x0
-#define TWL4030_PWMx_PWMxOFF 0x1
-
#define PWMxON_LENGTH BIT(7)
/*----------------------------------------------------------------------*/
@@ -145,7 +146,7 @@ static void twl4030_led_set_value(int led, int value)
else
cached_leden |= mask;
status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
- TWL4030_LED_LEDEN);
+ TWL4030_LED_LEDEN_REG);
mutex_unlock(&gpio_lock);
}
@@ -216,33 +217,33 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
if (offset >= TWL4030_GPIO_MAX) {
u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
- u8 module = TWL4030_MODULE_PWMA;
+ u8 reg = TWL4030_PWMAON_REG;
offset -= TWL4030_GPIO_MAX;
if (offset) {
ledclr_mask <<= 1;
- module = TWL4030_MODULE_PWMB;
+ reg = TWL4030_PWMBON_REG;
}
/* initialize PWM to always-drive */
- status = twl_i2c_write_u8(module, 0x7f,
- TWL4030_PWMx_PWMxOFF);
+ /* Configure PWM OFF register first */
+ status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg + 1);
if (status < 0)
goto done;
- status = twl_i2c_write_u8(module, 0x7f,
- TWL4030_PWMx_PWMxON);
+
+ /* Followed by PWM ON register */
+ status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg);
if (status < 0)
goto done;
/* init LED to not-driven (high) */
- module = TWL4030_MODULE_LED;
- status = twl_i2c_read_u8(module, &cached_leden,
- TWL4030_LED_LEDEN);
+ status = twl_i2c_read_u8(TWL4030_MODULE_LED, &cached_leden,
+ TWL4030_LED_LEDEN_REG);
if (status < 0)
goto done;
cached_leden &= ~ledclr_mask;
- status = twl_i2c_write_u8(module, cached_leden,
- TWL4030_LED_LEDEN);
+ status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
+ TWL4030_LED_LEDEN_REG);
if (status < 0)
goto done;
@@ -352,7 +353,7 @@ static struct gpio_chip twl_gpiochip = {
/*----------------------------------------------------------------------*/
-static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
+static int gpio_twl4030_pulls(u32 ups, u32 downs)
{
u8 message[6];
unsigned i, gpio_bit;
@@ -377,7 +378,7 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
REG_GPIOPUPDCTR1, 5);
}
-static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
{
u8 message[4];
@@ -419,7 +420,7 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
return omap_twl_info;
}
-static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
+static int gpio_twl4030_probe(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
@@ -505,7 +506,7 @@ out:
return ret;
}
-/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+/* Cannot use as gpio_twl4030_probe() calls us */
static int gpio_twl4030_remove(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
index dd58e8b25043..0be82c6dd796 100644
--- a/drivers/gpio/gpio-twl6040.c
+++ b/drivers/gpio/gpio-twl6040.c
@@ -82,7 +82,7 @@ static struct gpio_chip twl6040gpo_chip = {
/*----------------------------------------------------------------------*/
-static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+static int gpo_twl6040_probe(struct platform_device *pdev)
{
struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
struct device *twl6040_core_dev = pdev->dev.parent;
@@ -113,7 +113,7 @@ static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+static int gpo_twl6040_remove(struct platform_device *pdev)
{
return gpiochip_remove(&twl6040gpo_chip);
}
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
index 82d5c20ad3cb..9902732a382d 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -490,7 +490,7 @@ static struct gpio_chip vr41xx_gpio_chip = {
.to_irq = vr41xx_gpio_to_irq,
};
-static int __devinit giu_probe(struct platform_device *pdev)
+static int giu_probe(struct platform_device *pdev)
{
struct resource *res;
unsigned int trigger, i, pin;
@@ -552,7 +552,7 @@ static int __devinit giu_probe(struct platform_device *pdev)
return cascade_irq(irq, giu_get_irq);
}
-static int __devexit giu_remove(struct platform_device *pdev)
+static int giu_remove(struct platform_device *pdev)
{
if (giu_base) {
iounmap(giu_base);
@@ -564,7 +564,7 @@ static int __devexit giu_remove(struct platform_device *pdev)
static struct platform_driver giu_device_driver = {
.probe = giu_probe,
- .remove = __devexit_p(giu_remove),
+ .remove = giu_remove,
.driver = {
.name = "GIU",
.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
index bcd8e4aa7c7d..b53320a16fc8 100644
--- a/drivers/gpio/gpio-vt8500.c
+++ b/drivers/gpio/gpio-vt8500.c
@@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = {
VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
+ VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
},
};
@@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = {
VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
+ VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
},
};
@@ -269,7 +271,7 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {
{ /* Sentinel */ },
};
-static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
+static int vt8500_gpio_probe(struct platform_device *pdev)
{
void __iomem *gpio_base;
struct device_node *np;
diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c
index 76ebfe5ff702..2b7252cb2427 100644
--- a/drivers/gpio/gpio-vx855.c
+++ b/drivers/gpio/gpio-vx855.c
@@ -219,7 +219,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
}
/* This platform device is ordinarily registered by the vx855 mfd driver */
-static __devinit int vx855gpio_probe(struct platform_device *pdev)
+static int vx855gpio_probe(struct platform_device *pdev)
{
struct resource *res_gpi;
struct resource *res_gpo;
@@ -284,7 +284,7 @@ out_release:
return ret;
}
-static int __devexit vx855gpio_remove(struct platform_device *pdev)
+static int vx855gpio_remove(struct platform_device *pdev)
{
struct vx855_gpio *vg = platform_get_drvdata(pdev);
struct resource *res;
@@ -312,7 +312,7 @@ static struct platform_driver vx855gpio_driver = {
.owner = THIS_MODULE,
},
.probe = vx855gpio_probe,
- .remove = __devexit_p(vx855gpio_remove),
+ .remove = vx855gpio_remove,
};
module_platform_driver(vx855gpio_driver);
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index b6eda35089d5..2a743e10ecb6 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -243,7 +243,7 @@ static struct gpio_chip template_chip = {
.can_sleep = 1,
};
-static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
+static int wm831x_gpio_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -275,7 +275,7 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
+static int wm831x_gpio_remove(struct platform_device *pdev)
{
struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
@@ -286,7 +286,7 @@ static struct platform_driver wm831x_gpio_driver = {
.driver.name = "wm831x-gpio",
.driver.owner = THIS_MODULE,
.probe = wm831x_gpio_probe,
- .remove = __devexit_p(wm831x_gpio_remove),
+ .remove = wm831x_gpio_remove,
};
static int __init wm831x_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index fb4293889392..0b598cf3df9d 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -109,7 +109,7 @@ static struct gpio_chip template_chip = {
.can_sleep = 1,
};
-static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+static int wm8350_gpio_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
@@ -141,7 +141,7 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+static int wm8350_gpio_remove(struct platform_device *pdev)
{
struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
@@ -152,7 +152,7 @@ static struct platform_driver wm8350_gpio_driver = {
.driver.name = "wm8350-gpio",
.driver.owner = THIS_MODULE,
.probe = wm8350_gpio_probe,
- .remove = __devexit_p(wm8350_gpio_remove),
+ .remove = wm8350_gpio_remove,
};
static int __init wm8350_gpio_init(void)
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c
index 1c764e779d80..ae409fd94af7 100644
--- a/drivers/gpio/gpio-wm8994.c
+++ b/drivers/gpio/gpio-wm8994.c
@@ -245,7 +245,7 @@ static struct gpio_chip template_chip = {
.can_sleep = 1,
};
-static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+static int wm8994_gpio_probe(struct platform_device *pdev)
{
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -281,7 +281,7 @@ err:
return ret;
}
-static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+static int wm8994_gpio_remove(struct platform_device *pdev)
{
struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
@@ -292,7 +292,7 @@ static struct platform_driver wm8994_gpio_driver = {
.driver.name = "wm8994-gpio",
.driver.owner = THIS_MODULE,
.probe = wm8994_gpio_probe,
- .remove = __devexit_p(wm8994_gpio_remove),
+ .remove = wm8994_gpio_remove,
};
static int __init wm8994_gpio_init(void)
diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c
index 79b0fe8a7253..9ae7aa8ca48a 100644
--- a/drivers/gpio/gpio-xilinx.c
+++ b/drivers/gpio/gpio-xilinx.c
@@ -159,7 +159,7 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
* driver data structure. It returns 0, if the driver is bound to the GPIO
* device, or a negative value if there is an error.
*/
-static int __devinit xgpio_of_probe(struct device_node *np)
+static int xgpio_of_probe(struct device_node *np)
{
struct xgpio_instance *chip;
int status = 0;
@@ -209,7 +209,7 @@ static int __devinit xgpio_of_probe(struct device_node *np)
return 0;
}
-static struct of_device_id xgpio_of_match[] __devinitdata = {
+static struct of_device_id xgpio_of_match[] = {
{ .compatible = "xlnx,xps-gpio-1.00.a", },
{ /* end of list */ },
};
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
new file mode 100644
index 000000000000..cbad6e908d30
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -0,0 +1,54 @@
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ * Mika Westerberg <mika.westerberg@linux.intel.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/errno.h>
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/acpi_gpio.h>
+#include <linux/acpi.h>
+
+static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+{
+ if (!gc->dev)
+ return false;
+
+ return ACPI_HANDLE(gc->dev) == data;
+}
+
+/**
+ * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
+ * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
+ * @pin: ACPI GPIO pin number (0-based, controller-relative)
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or errno error value
+ */
+
+int acpi_get_gpio(char *path, int pin)
+{
+ struct gpio_chip *chip;
+ acpi_handle handle;
+ acpi_status status;
+
+ status = acpi_get_handle(NULL, path, &handle);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ chip = gpiochip_find(handle, acpi_gpiochip_find);
+ if (!chip)
+ return -ENODEV;
+
+ if (!gpio_is_valid(chip->base + pin))
+ return -EINVAL;
+
+ return chip->base + pin;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gpio);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a45997aea8..d542a141811a 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
/* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,54 @@ err0:
}
EXPORT_SYMBOL(of_mm_gpiochip_add);
+#ifdef CONFIG_PINCTRL
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+ struct device_node *np = chip->of_node;
+ struct of_phandle_args pinspec;
+ struct pinctrl_dev *pctldev;
+ int index = 0, ret;
+
+ if (!np)
+ return;
+
+ do {
+ ret = of_parse_phandle_with_args(np, "gpio-ranges",
+ "#gpio-range-cells", index, &pinspec);
+ if (ret)
+ break;
+
+ pctldev = of_pinctrl_get(pinspec.np);
+ if (!pctldev)
+ break;
+
+ /*
+ * This assumes that the n GPIO pins are consecutive in the
+ * GPIO number space, and that the pins are also consecutive
+ * in their local number space. Currently it is not possible
+ * to add different ranges for one and the same GPIO chip,
+ * as the code assumes that we have one consecutive range
+ * on both, mapping 1-to-1.
+ *
+ * TODO: make the OF bindings handle multiple sparse ranges
+ * on the same GPIO chip.
+ */
+ ret = gpiochip_add_pin_range(chip,
+ pinctrl_dev_get_name(pctldev),
+ 0, /* offset in gpiochip */
+ pinspec.args[0],
+ pinspec.args[1]);
+
+ if (ret)
+ break;
+
+ } while (index++);
+}
+
+#else
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+#endif
+
void of_gpiochip_add(struct gpio_chip *chip)
{
if ((!chip->of_node) && (chip->dev))
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
chip->of_xlate = of_gpio_simple_xlate;
}
+ of_gpiochip_add_pin_range(chip);
of_node_get(chip->of_node);
}
void of_gpiochip_remove(struct gpio_chip *chip)
{
+ gpiochip_remove_pin_ranges(chip);
+
if (chip->of_node)
of_node_put(chip->of_node);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1c8d9e3380e1..199fca15f270 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -191,6 +191,32 @@ err:
return ret;
}
+/* caller ensures gpio is valid and requested, chip->get_direction may sleep */
+static int gpio_get_direction(unsigned gpio)
+{
+ struct gpio_chip *chip;
+ struct gpio_desc *desc = &gpio_desc[gpio];
+ int status = -EINVAL;
+
+ chip = gpio_to_chip(gpio);
+ gpio -= chip->base;
+
+ if (!chip->get_direction)
+ return status;
+
+ status = chip->get_direction(chip, gpio);
+ if (status > 0) {
+ /* GPIOF_DIR_IN, or other positive */
+ status = 1;
+ clear_bit(FLAG_IS_OUT, &desc->flags);
+ }
+ if (status == 0) {
+ /* GPIOF_DIR_OUT */
+ set_bit(FLAG_IS_OUT, &desc->flags);
+ }
+ return status;
+}
+
#ifdef CONFIG_GPIO_SYSFS
/* lock protects against unexport_gpio() being called while
@@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_desc *desc = dev_get_drvdata(dev);
+ unsigned gpio = desc - gpio_desc;
ssize_t status;
mutex_lock(&sysfs_lock);
@@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev,
if (!test_bit(FLAG_EXPORT, &desc->flags))
status = -EIO;
else
+ gpio_get_direction(gpio);
status = sprintf(buf, "%s\n",
test_bit(FLAG_IS_OUT, &desc->flags)
? "out" : "in");
@@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
{
unsigned long flags;
struct gpio_desc *desc;
- int status = -EINVAL;
+ int status;
const char *ioname = NULL;
+ struct device *dev;
/* can't export until sysfs is available ... */
if (!gpio_class.p) {
@@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change)
return -ENOENT;
}
- if (!gpio_is_valid(gpio))
- goto done;
+ if (!gpio_is_valid(gpio)) {
+ pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
+ return -EINVAL;
+ }
mutex_lock(&sysfs_lock);
spin_lock_irqsave(&gpio_lock, flags);
desc = &gpio_desc[gpio];
- if (test_bit(FLAG_REQUESTED, &desc->flags)
- && !test_bit(FLAG_EXPORT, &desc->flags)) {
- status = 0;
- if (!desc->chip->direction_input
- || !desc->chip->direction_output)
- direction_may_change = false;
+ if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
+ test_bit(FLAG_EXPORT, &desc->flags)) {
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
+ __func__, gpio,
+ test_bit(FLAG_REQUESTED, &desc->flags),
+ test_bit(FLAG_EXPORT, &desc->flags));
+ status = -EPERM;
+ goto fail_unlock;
}
+
+ if (!desc->chip->direction_input || !desc->chip->direction_output)
+ direction_may_change = false;
spin_unlock_irqrestore(&gpio_lock, flags);
if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
ioname = desc->chip->names[gpio - desc->chip->base];
- if (status == 0) {
- struct device *dev;
-
- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
- desc, ioname ? ioname : "gpio%u", gpio);
- if (!IS_ERR(dev)) {
- status = sysfs_create_group(&dev->kobj,
- &gpio_attr_group);
-
- if (!status && direction_may_change)
- status = device_create_file(dev,
- &dev_attr_direction);
-
- if (!status && gpio_to_irq(gpio) >= 0
- && (direction_may_change
- || !test_bit(FLAG_IS_OUT,
- &desc->flags)))
- status = device_create_file(dev,
- &dev_attr_edge);
-
- if (status != 0)
- device_unregister(dev);
- } else
- status = PTR_ERR(dev);
- if (status == 0)
- set_bit(FLAG_EXPORT, &desc->flags);
+ dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
+ desc, ioname ? ioname : "gpio%u", gpio);
+ if (IS_ERR(dev)) {
+ status = PTR_ERR(dev);
+ goto fail_unlock;
}
- mutex_unlock(&sysfs_lock);
-
-done:
+ status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
if (status)
- pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+ goto fail_unregister_device;
+
+ if (direction_may_change) {
+ status = device_create_file(dev, &dev_attr_direction);
+ if (status)
+ goto fail_unregister_device;
+ }
+
+ if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
+ !test_bit(FLAG_IS_OUT, &desc->flags))) {
+ status = device_create_file(dev, &dev_attr_edge);
+ if (status)
+ goto fail_unregister_device;
+ }
+
+ set_bit(FLAG_EXPORT, &desc->flags);
+ mutex_unlock(&sysfs_lock);
+ return 0;
+fail_unregister_device:
+ device_unregister(dev);
+fail_unlock:
+ mutex_unlock(&sysfs_lock);
+ pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_export);
@@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip)
* inputs (often with pullups enabled) so power
* usage is minimized. Linux code should set the
* gpio direction first thing; but until it does,
+ * and in case chip->get_direction is not set,
* we may expose the wrong direction in sysfs.
*/
gpio_desc[id].flags = !chip->direction_input
@@ -1083,6 +1120,10 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
+#ifdef CONFIG_PINCTRL
+ INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
of_gpiochip_add(chip);
unlock:
@@ -1123,6 +1164,7 @@ int gpiochip_remove(struct gpio_chip *chip)
spin_lock_irqsave(&gpio_lock, flags);
+ gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@@ -1180,6 +1222,77 @@ struct gpio_chip *gpiochip_find(void *data,
}
EXPORT_SYMBOL_GPL(gpiochip_find);
+#ifdef CONFIG_PINCTRL
+
+/**
+ * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
+ * @chip: the gpiochip to add the range for
+ * @pinctrl_name: the dev_name() of the pin controller to map to
+ * @gpio_offset: the start offset in the current gpio_chip number space
+ * @pin_offset: the start offset in the pin controller number space
+ * @npins: the number of pins from the offset of each pin space (GPIO and
+ * pin controller) to accumulate in this range
+ */
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int gpio_offset, unsigned int pin_offset,
+ unsigned int npins)
+{
+ struct gpio_pin_range *pin_range;
+ int ret;
+
+ pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
+ if (!pin_range) {
+ pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+ chip->label);
+ return -ENOMEM;
+ }
+
+ /* Use local offset as range ID */
+ pin_range->range.id = gpio_offset;
+ pin_range->range.gc = chip;
+ pin_range->range.name = chip->label;
+ pin_range->range.base = chip->base + gpio_offset;
+ pin_range->range.pin_base = pin_offset;
+ pin_range->range.npins = npins;
+ pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
+ &pin_range->range);
+ if (IS_ERR(pin_range->pctldev)) {
+ ret = PTR_ERR(pin_range->pctldev);
+ pr_err("%s: GPIO chip: could not create pin range\n",
+ chip->label);
+ kfree(pin_range);
+ return ret;
+ }
+ pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n",
+ chip->label, gpio_offset, gpio_offset + npins - 1,
+ pinctl_name,
+ pin_offset, pin_offset + npins - 1);
+
+ list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
+
+/**
+ * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
+ * @chip: the chip to remove all the mappings for
+ */
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+ struct gpio_pin_range *pin_range, *tmp;
+
+ list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+ list_del(&pin_range->node);
+ pinctrl_remove_gpio_range(pin_range->pctldev,
+ &pin_range->range);
+ kfree(pin_range);
+ }
+}
+EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
+
+#endif /* CONFIG_PINCTRL */
+
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls.
@@ -1228,9 +1341,15 @@ int gpio_request(unsigned gpio, const char *label)
desc_set_label(desc, NULL);
module_put(chip->owner);
clear_bit(FLAG_REQUESTED, &desc->flags);
+ goto done;
}
}
-
+ if (chip->get_direction) {
+ /* chip->get_direction may sleep */
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ gpio_get_direction(gpio);
+ spin_lock_irqsave(&gpio_lock, flags);
+ }
done:
if (status)
pr_debug("gpio_request: gpio-%d (%s) status %d\n",
@@ -1766,6 +1885,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
continue;
+ gpio_get_direction(gpio);
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
gpio, gdesc->label,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 241ad1eeec64..f2df06c603f7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -226,6 +226,12 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
* already updated or not by exynos_drm_encoder_dpms function.
*/
exynos_encoder->updated = true;
+
+ /*
+ * In case of setcrtc, there is no way to update encoder's dpms
+ * so update it here.
+ */
+ exynos_encoder->dpms = DRM_MODE_DPMS_ON;
}
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -507,6 +513,6 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
* because the setting for disabling the overlay will be updated
* at vsync.
*/
- if (overlay_ops->wait_for_vblank)
+ if (overlay_ops && overlay_ops->wait_for_vblank)
overlay_ops->wait_for_vblank(manager->dev);
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 67eb6ba56edf..e7466c4414cb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -87,7 +87,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
fbi->screen_base = buffer->kvaddr + offset;
- fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
+ fbi->fix.smem_start = (unsigned long)(page_to_phys(buffer->pages[0]) +
+ offset);
fbi->screen_size = size;
fbi->fix.smem_len = size;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 130a2b510d4a..e08478f19f1a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -61,11 +61,11 @@ struct fimd_driver_data {
unsigned int timing_base;
};
-struct fimd_driver_data exynos4_fimd_driver_data = {
+static struct fimd_driver_data exynos4_fimd_driver_data = {
.timing_base = 0x0,
};
-struct fimd_driver_data exynos5_fimd_driver_data = {
+static struct fimd_driver_data exynos5_fimd_driver_data = {
.timing_base = 0x20000,
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 60b877a388c2..862ca1eb2102 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -204,7 +204,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
return ret;
plane->crtc = crtc;
- plane->fb = crtc->fb;
exynos_plane_commit(plane);
exynos_plane_dpms(plane, DRM_MODE_DPMS_ON);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 107f09befe92..9b285da4449b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1796,7 +1796,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
*/
mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
gfp = mapping_gfp_mask(mapping);
- gfp |= __GFP_NORETRY | __GFP_NOWARN;
+ gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
gfp &= ~(__GFP_IO | __GFP_WAIT);
for_each_sg(st->sgl, sg, page_count, i) {
page = shmem_read_mapping_page_gfp(mapping, i, gfp);
@@ -1809,7 +1809,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
* our own buffer, now let the real VM do its job and
* go down in flames if truly OOM.
*/
- gfp &= ~(__GFP_NORETRY | __GFP_NOWARN);
+ gfp &= ~(__GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD);
gfp |= __GFP_IO | __GFP_WAIT;
i915_gem_shrink_all(dev_priv);
@@ -1817,7 +1817,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
if (IS_ERR(page))
goto err_pages;
- gfp |= __GFP_NORETRY | __GFP_NOWARN;
+ gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
gfp &= ~(__GFP_IO | __GFP_WAIT);
}
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 0ed6baff4b0c..56846ed5ee55 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -499,12 +499,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
edp = find_section(bdb, BDB_EDP);
if (!edp) {
- if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) {
- DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
- "supported, assume %dbpp panel color "
- "depth.\n",
- dev_priv->edp.bpp);
- }
+ if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support)
+ DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
return;
}
@@ -657,9 +653,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
dev_priv->lvds_use_ssc = 1;
dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
-
- /* eDP data */
- dev_priv->edp.bpp = 18;
}
static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4154bcd7a070..b426d44a2b05 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3845,7 +3845,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
/* Use VBT settings if we have an eDP panel */
unsigned int edp_bpc = dev_priv->edp.bpp / 3;
- if (edp_bpc < display_bpc) {
+ if (edp_bpc && edp_bpc < display_bpc) {
DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
display_bpc = edp_bpc;
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 72f41aaa71ff..442968f8b201 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2373,15 +2373,9 @@ int intel_enable_rc6(const struct drm_device *dev)
if (i915_enable_rc6 >= 0)
return i915_enable_rc6;
- if (INTEL_INFO(dev)->gen == 5) {
-#ifdef CONFIG_INTEL_IOMMU
- /* Disable rc6 on ilk if VT-d is on. */
- if (intel_iommu_gfx_mapped)
- return false;
-#endif
- DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n");
- return INTEL_RC6_ENABLE;
- }
+ /* Disable RC6 on Ironlake */
+ if (INTEL_INFO(dev)->gen == 5)
+ return 0;
if (IS_HASWELL(dev)) {
DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index c600fb06e25e..a6ac0b416964 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2201,7 +2201,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
intel_sdvo->is_hdmi = true;
}
- intel_sdvo->base.cloneable = true;
intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
if (intel_sdvo->is_hdmi)
@@ -2232,7 +2231,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
intel_sdvo->is_tv = true;
intel_sdvo->base.needs_tv_clock = true;
- intel_sdvo->base.cloneable = false;
intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
@@ -2275,8 +2273,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
}
- intel_sdvo->base.cloneable = true;
-
intel_sdvo_connector_init(intel_sdvo_connector,
intel_sdvo);
return true;
@@ -2307,9 +2303,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
}
- /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
- intel_sdvo->base.cloneable = false;
-
intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
goto err;
@@ -2721,6 +2714,16 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
goto err_output;
}
+ /*
+ * Cloning SDVO with anything is often impossible, since the SDVO
+ * encoder can request a special input timing mode. And even if that's
+ * not the case we have evidence that cloning a plain unscaled mode with
+ * VGA doesn't really work. Furthermore the cloning flags are way too
+ * simplistic anyway to express such constraints, so just give up on
+ * cloning for SDVO encoders.
+ */
+ intel_sdvo->base.cloneable = false;
+
/* Only enable the hotplug irq if we need it, to work around noisy
* hotplug lines.
*/
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 05a909a17cee..15b182c84ce8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -49,13 +49,7 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
if (chan->vblank.crtc != crtc)
continue;
- if (nv_device(priv)->chipset == 0x50) {
- nv_wr32(priv, 0x001704, chan->vblank.channel);
- nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
- bar->flush(bar);
- nv_wr32(priv, 0x001570, chan->vblank.offset);
- nv_wr32(priv, 0x001574, chan->vblank.value);
- } else {
+ if (nv_device(priv)->chipset >= 0xc0) {
nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
bar->flush(bar);
nv_wr32(priv, 0x06000c,
@@ -63,6 +57,17 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
nv_wr32(priv, 0x060010,
lower_32_bits(chan->vblank.offset));
nv_wr32(priv, 0x060014, chan->vblank.value);
+ } else {
+ nv_wr32(priv, 0x001704, chan->vblank.channel);
+ nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+ bar->flush(bar);
+ if (nv_device(priv)->chipset == 0x50) {
+ nv_wr32(priv, 0x001570, chan->vblank.offset);
+ nv_wr32(priv, 0x001574, chan->vblank.value);
+ } else {
+ nv_wr32(priv, 0x060010, chan->vblank.offset);
+ nv_wr32(priv, 0x060014, chan->vblank.value);
+ }
}
list_del(&chan->vblank.head);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
index e45035efb8ca..7bbb1e1b7a8d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem)
});
}
-void
+int
nv40_grctx_init(struct nouveau_device *device, u32 *size)
{
- u32 ctxprog[256], i;
+ u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;
struct nouveau_grctx ctx = {
.device = device,
.mode = NOUVEAU_GRCTX_PROG,
.data = ctxprog,
- .ctxprog_max = ARRAY_SIZE(ctxprog)
+ .ctxprog_max = 256,
};
+ if (!ctxprog)
+ return -ENOMEM;
+
nv40_grctx_generate(&ctx);
nv_wr32(device, 0x400324, 0);
for (i = 0; i < ctx.ctxprog_len; i++)
nv_wr32(device, 0x400328, ctxprog[i]);
*size = ctx.ctxvals_pos * 4;
+
+ kfree(ctxprog);
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
index 425001204a89..cc6574eeb80e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object)
return ret;
/* generate and upload context program */
- nv40_grctx_init(nv_device(priv), &priv->size);
+ ret = nv40_grctx_init(nv_device(priv), &priv->size);
+ if (ret)
+ return ret;
/* No context present currently */
nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
index d2ac975afc2e..7da35a4e7970 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv)
return !(0x0baf & (1 << (device->chipset & 0x0f)));
}
-void nv40_grctx_init(struct nouveau_device *, u32 *size);
+int nv40_grctx_init(struct nouveau_device *, u32 *size);
void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *);
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h
index 818feabbf4a0..486f1a9217fd 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/object.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/object.h
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data)
return temp;
}
-static inline bool
-nv_strncmp(void *obj, u32 addr, u32 len, const char *str)
+static inline int
+nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
{
+ unsigned char c1, c2;
+
while (len--) {
- if (nv_ro08(obj, addr++) != *(str++))
- return false;
+ c1 = nv_ro08(obj, addr++);
+ c2 = *(str++);
+ if (c1 != c2)
+ return c1 - c2;
}
- return true;
+ return 0;
}
#endif
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
index 39e73b91d360..41b7a6a76f19 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
int clk, struct nouveau_pll_vals *);
int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
struct nouveau_pll_vals *);
-
+int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
+ int clk, struct nouveau_pll_vals *);
#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
index 7d750382a833..c51197157749 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
}
} else
if (*ver >= 0x15) {
- if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) {
+ if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
u16 i2c = nv_ro16(bios, dcb + 2);
*hdr = 4;
*cnt = (i2c - dcb) / 10;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
index cc8d7d162d7c..9068c98b96f6 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
return ret;
}
+int
+nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
+ int clk, struct nouveau_pll_vals *pv)
+{
+ int ret, N, M, P;
+
+ ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P);
+
+ if (ret > 0) {
+ pv->refclk = info->refclk;
+ pv->N1 = N;
+ pv->M1 = M;
+ pv->log2P = P;
+ }
+ return ret;
+}
+
+
static int
nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
priv->base.pll_set = nva3_clock_pll_set;
+ priv->base.pll_calc = nva3_clock_pll_calc;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
index 5ccce0b17bf3..f6962c9b6c36 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
priv->base.pll_set = nvc0_clock_pll_set;
+ priv->base.pll_calc = nva3_clock_pll_calc;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index cc79c796afee..cbf1fc60a386 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
if (unlikely(!abi16))
return -ENOMEM;
+
+ if (!drm->channel)
+ return nouveau_abi16_put(abi16, -ENODEV);
+
client = nv_client(abi16->client);
if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 0910125cbbc3..8503b2ea570a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -129,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
/* initialise synchronisation routines */
if (device->card_type < NV_10) ret = nv04_fence_create(drm);
- else if (device->chipset < 0x84) ret = nv10_fence_create(drm);
+ else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+ else if (device->chipset < 0x84) ret = nv50_fence_create(drm);
else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
else ret = nvc0_fence_create(drm);
if (ret) {
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 3bce0299f64a..24d932f53203 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1696,42 +1696,22 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
return ATOM_PPLL2;
DRM_ERROR("unable to allocate a PPLL\n");
return ATOM_PPLL_INVALID;
- } else if (ASIC_IS_AVIVO(rdev)) {
- /* in DP mode, the DP ref clock can come from either PPLL
- * depending on the asic:
- * DCE3: PPLL1 or PPLL2
- */
- if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
- /* use the same PPLL for all DP monitors */
- pll = radeon_get_shared_dp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- } else {
- /* use the same PPLL for all monitors with the same clock */
- pll = radeon_get_shared_nondp_ppll(crtc);
- if (pll != ATOM_PPLL_INVALID)
- return pll;
- }
- /* all other cases */
- pll_in_use = radeon_get_pll_use_mask(crtc);
- /* the order shouldn't matter here, but we probably
- * need this until we have atomic modeset
- */
- if (rdev->flags & RADEON_IS_IGP) {
- if (!(pll_in_use & (1 << ATOM_PPLL1)))
- return ATOM_PPLL1;
- if (!(pll_in_use & (1 << ATOM_PPLL2)))
- return ATOM_PPLL2;
- } else {
- if (!(pll_in_use & (1 << ATOM_PPLL2)))
- return ATOM_PPLL2;
- if (!(pll_in_use & (1 << ATOM_PPLL1)))
- return ATOM_PPLL1;
- }
- DRM_ERROR("unable to allocate a PPLL\n");
- return ATOM_PPLL_INVALID;
} else {
/* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+ /* some atombios (observed in some DCE2/DCE3) code have a bug,
+ * the matching btw pll and crtc is done through
+ * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the
+ * pll (1 or 2) to select which register to write. ie if using
+ * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2
+ * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to
+ * choose which value to write. Which is reverse order from
+ * register logic. So only case that works is when pllid is
+ * same as crtcid or when both pll and crtc are enabled and
+ * both use same clock.
+ *
+ * So just return crtc id as if crtc and pll were hard linked
+ * together even if they aren't
+ */
return radeon_crtc->crtc_id;
}
}
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index af31f829f4a8..219942c660d7 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
break;
udelay(1);
}
+ } else {
+ save->crtc_enabled[i] = false;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
index 10ea17a6b2a6..42433344cb1b 100644
--- a/drivers/gpu/drm/radeon/radeon_agp.c
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
/* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
{ PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
PCI_VENDOR_ID_DELL, 0x00e3, 2},
- /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+ /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */
{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
PCI_VENDOR_ID_DELL, 0x0149, 1},
+ /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */
+ { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
+ PCI_VENDOR_ID_IBM, 0x0531, 1},
/* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
{ PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
0x1025, 0x0061, 1},
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 70f5dde1cc52..b38ef6d8d049 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -13,4 +13,10 @@ config HYPERV_UTILS
help
Select this option to enable the Hyper-V Utilities.
+config HYPERV_BALLOON
+ tristate "Microsoft Hyper-V Balloon driver"
+ depends on HYPERV
+ help
+ Select this option to enable Hyper-V Balloon driver.
+
endmenu
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile
index a23938b991c9..e6abfa02d8b7 100644
--- a/drivers/hv/Makefile
+++ b/drivers/hv/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_HYPERV) += hv_vmbus.o
obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o
+obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o
hv_vmbus-y := vmbus_drv.o \
hv.o connection.o channel.o \
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index f4c3d28cd1fc..773a2f25a8f0 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -33,14 +33,6 @@
#define NUM_PAGES_SPANNED(addr, len) \
((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
-/* Internal routines */
-static int create_gpadl_header(
- void *kbuffer, /* must be phys and virt contiguous */
- u32 size, /* page-size multiple */
- struct vmbus_channel_msginfo **msginfo,
- u32 *messagecount);
-static void vmbus_setevent(struct vmbus_channel *channel);
-
/*
* vmbus_setevent- Trigger an event notification on the specified
* channel.
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 2b8b8d4558d2..2f84c5cff8d4 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -265,14 +265,9 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
{
struct vmbus_channel_offer_channel *offer;
struct vmbus_channel *newchannel;
- uuid_le *guidtype;
- uuid_le *guidinstance;
offer = (struct vmbus_channel_offer_channel *)hdr;
- guidtype = &offer->offer.if_type;
- guidinstance = &offer->offer.if_instance;
-
/* Allocate the channel object and save this offer. */
newchannel = alloc_channel();
if (!newchannel) {
@@ -470,7 +465,6 @@ static void vmbus_onversion_response(
{
struct vmbus_channel_msginfo *msginfo;
struct vmbus_channel_message_header *requestheader;
- struct vmbus_channel_initiate_contact *initiate;
struct vmbus_channel_version_response *version_response;
unsigned long flags;
@@ -484,8 +478,6 @@ static void vmbus_onversion_response(
if (requestheader->msgtype ==
CHANNELMSG_INITIATE_CONTACT) {
- initiate =
- (struct vmbus_channel_initiate_contact *)requestheader;
memcpy(&msginfo->response.version_response,
version_response,
sizeof(struct vmbus_channel_version_response));
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
new file mode 100644
index 000000000000..f6c0011a0337
--- /dev/null
+++ b/drivers/hv/hv_balloon.c
@@ -0,0 +1,1041 @@
+/*
+ * Copyright (c) 2012, Microsoft Corporation.
+ *
+ * Author:
+ * K. Y. Srinivasan <kys@microsoft.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, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/mman.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/completion.h>
+#include <linux/memory_hotplug.h>
+#include <linux/memory.h>
+#include <linux/notifier.h>
+#include <linux/mman.h>
+#include <linux/percpu_counter.h>
+
+#include <linux/hyperv.h>
+
+/*
+ * We begin with definitions supporting the Dynamic Memory protocol
+ * with the host.
+ *
+ * Begin protocol definitions.
+ */
+
+
+
+/*
+ * Protocol versions. The low word is the minor version, the high word the major
+ * version.
+ *
+ * History:
+ * Initial version 1.0
+ * Changed to 0.1 on 2009/03/25
+ * Changes to 0.2 on 2009/05/14
+ * Changes to 0.3 on 2009/12/03
+ * Changed to 1.0 on 2011/04/05
+ */
+
+#define DYNMEM_MAKE_VERSION(Major, Minor) ((__u32)(((Major) << 16) | (Minor)))
+#define DYNMEM_MAJOR_VERSION(Version) ((__u32)(Version) >> 16)
+#define DYNMEM_MINOR_VERSION(Version) ((__u32)(Version) & 0xff)
+
+enum {
+ DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3),
+ DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0),
+
+ DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1,
+ DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2,
+
+ DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN8
+};
+
+
+
+/*
+ * Message Types
+ */
+
+enum dm_message_type {
+ /*
+ * Version 0.3
+ */
+ DM_ERROR = 0,
+ DM_VERSION_REQUEST = 1,
+ DM_VERSION_RESPONSE = 2,
+ DM_CAPABILITIES_REPORT = 3,
+ DM_CAPABILITIES_RESPONSE = 4,
+ DM_STATUS_REPORT = 5,
+ DM_BALLOON_REQUEST = 6,
+ DM_BALLOON_RESPONSE = 7,
+ DM_UNBALLOON_REQUEST = 8,
+ DM_UNBALLOON_RESPONSE = 9,
+ DM_MEM_HOT_ADD_REQUEST = 10,
+ DM_MEM_HOT_ADD_RESPONSE = 11,
+ DM_VERSION_03_MAX = 11,
+ /*
+ * Version 1.0.
+ */
+ DM_INFO_MESSAGE = 12,
+ DM_VERSION_1_MAX = 12
+};
+
+
+/*
+ * Structures defining the dynamic memory management
+ * protocol.
+ */
+
+union dm_version {
+ struct {
+ __u16 minor_version;
+ __u16 major_version;
+ };
+ __u32 version;
+} __packed;
+
+
+union dm_caps {
+ struct {
+ __u64 balloon:1;
+ __u64 hot_add:1;
+ __u64 reservedz:62;
+ } cap_bits;
+ __u64 caps;
+} __packed;
+
+union dm_mem_page_range {
+ struct {
+ /*
+ * The PFN number of the first page in the range.
+ * 40 bits is the architectural limit of a PFN
+ * number for AMD64.
+ */
+ __u64 start_page:40;
+ /*
+ * The number of pages in the range.
+ */
+ __u64 page_cnt:24;
+ } finfo;
+ __u64 page_range;
+} __packed;
+
+
+
+/*
+ * The header for all dynamic memory messages:
+ *
+ * type: Type of the message.
+ * size: Size of the message in bytes; including the header.
+ * trans_id: The guest is responsible for manufacturing this ID.
+ */
+
+struct dm_header {
+ __u16 type;
+ __u16 size;
+ __u32 trans_id;
+} __packed;
+
+/*
+ * A generic message format for dynamic memory.
+ * Specific message formats are defined later in the file.
+ */
+
+struct dm_message {
+ struct dm_header hdr;
+ __u8 data[]; /* enclosed message */
+} __packed;
+
+
+/*
+ * Specific message types supporting the dynamic memory protocol.
+ */
+
+/*
+ * Version negotiation message. Sent from the guest to the host.
+ * The guest is free to try different versions until the host
+ * accepts the version.
+ *
+ * dm_version: The protocol version requested.
+ * is_last_attempt: If TRUE, this is the last version guest will request.
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_request {
+ struct dm_header hdr;
+ union dm_version version;
+ __u32 is_last_attempt:1;
+ __u32 reservedz:31;
+} __packed;
+
+/*
+ * Version response message; Host to Guest and indicates
+ * if the host has accepted the version sent by the guest.
+ *
+ * is_accepted: If TRUE, host has accepted the version and the guest
+ * should proceed to the next stage of the protocol. FALSE indicates that
+ * guest should re-try with a different version.
+ *
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct dm_version_response {
+ struct dm_header hdr;
+ __u64 is_accepted:1;
+ __u64 reservedz:63;
+} __packed;
+
+/*
+ * Message reporting capabilities. This is sent from the guest to the
+ * host.
+ */
+
+struct dm_capabilities {
+ struct dm_header hdr;
+ union dm_caps caps;
+ __u64 min_page_cnt;
+ __u64 max_page_number;
+} __packed;
+
+/*
+ * Response to the capabilities message. This is sent from the host to the
+ * guest. This message notifies if the host has accepted the guest's
+ * capabilities. If the host has not accepted, the guest must shutdown
+ * the service.
+ *
+ * is_accepted: Indicates if the host has accepted guest's capabilities.
+ * reservedz: Must be 0.
+ */
+
+struct dm_capabilities_resp_msg {
+ struct dm_header hdr;
+ __u64 is_accepted:1;
+ __u64 reservedz:63;
+} __packed;
+
+/*
+ * This message is used to report memory pressure from the guest.
+ * This message is not part of any transaction and there is no
+ * response to this message.
+ *
+ * num_avail: Available memory in pages.
+ * num_committed: Committed memory in pages.
+ * page_file_size: The accumulated size of all page files
+ * in the system in pages.
+ * zero_free: The nunber of zero and free pages.
+ * page_file_writes: The writes to the page file in pages.
+ * io_diff: An indicator of file cache efficiency or page file activity,
+ * calculated as File Cache Page Fault Count - Page Read Count.
+ * This value is in pages.
+ *
+ * Some of these metrics are Windows specific and fortunately
+ * the algorithm on the host side that computes the guest memory
+ * pressure only uses num_committed value.
+ */
+
+struct dm_status {
+ struct dm_header hdr;
+ __u64 num_avail;
+ __u64 num_committed;
+ __u64 page_file_size;
+ __u64 zero_free;
+ __u32 page_file_writes;
+ __u32 io_diff;
+} __packed;
+
+
+/*
+ * Message to ask the guest to allocate memory - balloon up message.
+ * This message is sent from the host to the guest. The guest may not be
+ * able to allocate as much memory as requested.
+ *
+ * num_pages: number of pages to allocate.
+ */
+
+struct dm_balloon {
+ struct dm_header hdr;
+ __u32 num_pages;
+ __u32 reservedz;
+} __packed;
+
+
+/*
+ * Balloon response message; this message is sent from the guest
+ * to the host in response to the balloon message.
+ *
+ * reservedz: Reserved; must be set to zero.
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will atleast one more message from the guest.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_balloon_response {
+ struct dm_header hdr;
+ __u32 reservedz;
+ __u32 more_pages:1;
+ __u32 range_count:31;
+ union dm_mem_page_range range_array[];
+} __packed;
+
+/*
+ * Un-balloon message; this message is sent from the host
+ * to the guest to give guest more memory.
+ *
+ * more_pages: If FALSE, this is the last message of the transaction.
+ * if TRUE there will atleast one more message from the guest.
+ *
+ * reservedz: Reserved; must be set to zero.
+ *
+ * range_count: The number of ranges in the range array.
+ *
+ * range_array: An array of page ranges returned to the host.
+ *
+ */
+
+struct dm_unballoon_request {
+ struct dm_header hdr;
+ __u32 more_pages:1;
+ __u32 reservedz:31;
+ __u32 range_count;
+ union dm_mem_page_range range_array[];
+} __packed;
+
+/*
+ * Un-balloon response message; this message is sent from the guest
+ * to the host in response to an unballoon request.
+ *
+ */
+
+struct dm_unballoon_response {
+ struct dm_header hdr;
+} __packed;
+
+
+/*
+ * Hot add request message. Message sent from the host to the guest.
+ *
+ * mem_range: Memory range to hot add.
+ *
+ * On Linux we currently don't support this since we cannot hot add
+ * arbitrary granularity of memory.
+ */
+
+struct dm_hot_add {
+ struct dm_header hdr;
+ union dm_mem_page_range range;
+} __packed;
+
+/*
+ * Hot add response message.
+ * This message is sent by the guest to report the status of a hot add request.
+ * If page_count is less than the requested page count, then the host should
+ * assume all further hot add requests will fail, since this indicates that
+ * the guest has hit an upper physical memory barrier.
+ *
+ * Hot adds may also fail due to low resources; in this case, the guest must
+ * not complete this message until the hot add can succeed, and the host must
+ * not send a new hot add request until the response is sent.
+ * If VSC fails to hot add memory DYNMEM_NUMBER_OF_UNSUCCESSFUL_HOTADD_ATTEMPTS
+ * times it fails the request.
+ *
+ *
+ * page_count: number of pages that were successfully hot added.
+ *
+ * result: result of the operation 1: success, 0: failure.
+ *
+ */
+
+struct dm_hot_add_response {
+ struct dm_header hdr;
+ __u32 page_count;
+ __u32 result;
+} __packed;
+
+/*
+ * Types of information sent from host to the guest.
+ */
+
+enum dm_info_type {
+ INFO_TYPE_MAX_PAGE_CNT = 0,
+ MAX_INFO_TYPE
+};
+
+
+/*
+ * Header for the information message.
+ */
+
+struct dm_info_header {
+ enum dm_info_type type;
+ __u32 data_size;
+} __packed;
+
+/*
+ * This message is sent from the host to the guest to pass
+ * some relevant information (win8 addition).
+ *
+ * reserved: no used.
+ * info_size: size of the information blob.
+ * info: information blob.
+ */
+
+struct dm_info_msg {
+ struct dm_info_header header;
+ __u32 reserved;
+ __u32 info_size;
+ __u8 info[];
+};
+
+/*
+ * End protocol definitions.
+ */
+
+static bool hot_add;
+static bool do_hot_add;
+
+module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
+MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
+
+static atomic_t trans_id = ATOMIC_INIT(0);
+
+static int dm_ring_size = (5 * PAGE_SIZE);
+
+/*
+ * Driver specific state.
+ */
+
+enum hv_dm_state {
+ DM_INITIALIZING = 0,
+ DM_INITIALIZED,
+ DM_BALLOON_UP,
+ DM_BALLOON_DOWN,
+ DM_HOT_ADD,
+ DM_INIT_ERROR
+};
+
+
+static __u8 recv_buffer[PAGE_SIZE];
+static __u8 *send_buffer;
+#define PAGES_IN_2M 512
+
+struct hv_dynmem_device {
+ struct hv_device *dev;
+ enum hv_dm_state state;
+ struct completion host_event;
+ struct completion config_event;
+
+ /*
+ * Number of pages we have currently ballooned out.
+ */
+ unsigned int num_pages_ballooned;
+
+ /*
+ * This thread handles both balloon/hot-add
+ * requests from the host as well as notifying
+ * the host with regards to memory pressure in
+ * the guest.
+ */
+ struct task_struct *thread;
+
+ /*
+ * We start with the highest version we can support
+ * and downgrade based on the host; we save here the
+ * next version to try.
+ */
+ __u32 next_version;
+};
+
+static struct hv_dynmem_device dm_device;
+
+static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg)
+{
+
+ struct dm_hot_add_response resp;
+
+ if (do_hot_add) {
+
+ pr_info("Memory hot add not supported\n");
+
+ /*
+ * Currently we do not support hot add.
+ * Just fail the request.
+ */
+ }
+
+ memset(&resp, 0, sizeof(struct dm_hot_add_response));
+ resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE;
+ resp.hdr.size = sizeof(struct dm_hot_add_response);
+ resp.hdr.trans_id = atomic_inc_return(&trans_id);
+
+ resp.page_count = 0;
+ resp.result = 0;
+
+ dm->state = DM_INITIALIZED;
+ vmbus_sendpacket(dm->dev->channel, &resp,
+ sizeof(struct dm_hot_add_response),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND, 0);
+
+}
+
+static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
+{
+ switch (msg->header.type) {
+ case INFO_TYPE_MAX_PAGE_CNT:
+ pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
+ pr_info("Data Size is %d\n", msg->header.data_size);
+ break;
+ default:
+ pr_info("Received Unknown type: %d\n", msg->header.type);
+ }
+}
+
+/*
+ * Post our status as it relates memory pressure to the
+ * host. Host expects the guests to post this status
+ * periodically at 1 second intervals.
+ *
+ * The metrics specified in this protocol are very Windows
+ * specific and so we cook up numbers here to convey our memory
+ * pressure.
+ */
+
+static void post_status(struct hv_dynmem_device *dm)
+{
+ struct dm_status status;
+
+
+ memset(&status, 0, sizeof(struct dm_status));
+ status.hdr.type = DM_STATUS_REPORT;
+ status.hdr.size = sizeof(struct dm_status);
+ status.hdr.trans_id = atomic_inc_return(&trans_id);
+
+
+ status.num_committed = vm_memory_committed();
+
+ vmbus_sendpacket(dm->dev->channel, &status,
+ sizeof(struct dm_status),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND, 0);
+
+}
+
+
+
+static void free_balloon_pages(struct hv_dynmem_device *dm,
+ union dm_mem_page_range *range_array)
+{
+ int num_pages = range_array->finfo.page_cnt;
+ __u64 start_frame = range_array->finfo.start_page;
+ struct page *pg;
+ int i;
+
+ for (i = 0; i < num_pages; i++) {
+ pg = pfn_to_page(i + start_frame);
+ __free_page(pg);
+ dm->num_pages_ballooned--;
+ }
+}
+
+
+
+static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
+ struct dm_balloon_response *bl_resp, int alloc_unit,
+ bool *alloc_error)
+{
+ int i = 0;
+ struct page *pg;
+
+ if (num_pages < alloc_unit)
+ return 0;
+
+ for (i = 0; (i * alloc_unit) < num_pages; i++) {
+ if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) >
+ PAGE_SIZE)
+ return i * alloc_unit;
+
+ /*
+ * We execute this code in a thread context. Furthermore,
+ * we don't want the kernel to try too hard.
+ */
+ pg = alloc_pages(GFP_HIGHUSER | __GFP_NORETRY |
+ __GFP_NOMEMALLOC | __GFP_NOWARN,
+ get_order(alloc_unit << PAGE_SHIFT));
+
+ if (!pg) {
+ *alloc_error = true;
+ return i * alloc_unit;
+ }
+
+
+ dm->num_pages_ballooned += alloc_unit;
+
+ bl_resp->range_count++;
+ bl_resp->range_array[i].finfo.start_page =
+ page_to_pfn(pg);
+ bl_resp->range_array[i].finfo.page_cnt = alloc_unit;
+ bl_resp->hdr.size += sizeof(union dm_mem_page_range);
+
+ }
+
+ return num_pages;
+}
+
+
+
+static void balloon_up(struct hv_dynmem_device *dm, struct dm_balloon *req)
+{
+ int num_pages = req->num_pages;
+ int num_ballooned = 0;
+ struct dm_balloon_response *bl_resp;
+ int alloc_unit;
+ int ret;
+ bool alloc_error = false;
+ bool done = false;
+ int i;
+
+
+ /*
+ * Currently, we only support 4k allocations.
+ */
+ alloc_unit = 1;
+
+ while (!done) {
+ bl_resp = (struct dm_balloon_response *)send_buffer;
+ memset(send_buffer, 0, PAGE_SIZE);
+ bl_resp->hdr.type = DM_BALLOON_RESPONSE;
+ bl_resp->hdr.trans_id = atomic_inc_return(&trans_id);
+ bl_resp->hdr.size = sizeof(struct dm_balloon_response);
+ bl_resp->more_pages = 1;
+
+
+ num_pages -= num_ballooned;
+ num_ballooned = alloc_balloon_pages(dm, num_pages,
+ bl_resp, alloc_unit,
+ &alloc_error);
+
+ if ((alloc_error) || (num_ballooned == num_pages)) {
+ bl_resp->more_pages = 0;
+ done = true;
+ dm->state = DM_INITIALIZED;
+ }
+
+ /*
+ * We are pushing a lot of data through the channel;
+ * deal with transient failures caused because of the
+ * lack of space in the ring buffer.
+ */
+
+ do {
+ ret = vmbus_sendpacket(dm_device.dev->channel,
+ bl_resp,
+ bl_resp->hdr.size,
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND, 0);
+
+ if (ret == -EAGAIN)
+ msleep(20);
+
+ } while (ret == -EAGAIN);
+
+ if (ret) {
+ /*
+ * Free up the memory we allocatted.
+ */
+ pr_info("Balloon response failed\n");
+
+ for (i = 0; i < bl_resp->range_count; i++)
+ free_balloon_pages(dm,
+ &bl_resp->range_array[i]);
+
+ done = true;
+ }
+ }
+
+}
+
+static void balloon_down(struct hv_dynmem_device *dm,
+ struct dm_unballoon_request *req)
+{
+ union dm_mem_page_range *range_array = req->range_array;
+ int range_count = req->range_count;
+ struct dm_unballoon_response resp;
+ int i;
+
+ for (i = 0; i < range_count; i++)
+ free_balloon_pages(dm, &range_array[i]);
+
+ if (req->more_pages == 1)
+ return;
+
+ memset(&resp, 0, sizeof(struct dm_unballoon_response));
+ resp.hdr.type = DM_UNBALLOON_RESPONSE;
+ resp.hdr.trans_id = atomic_inc_return(&trans_id);
+ resp.hdr.size = sizeof(struct dm_unballoon_response);
+
+ vmbus_sendpacket(dm_device.dev->channel, &resp,
+ sizeof(struct dm_unballoon_response),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND, 0);
+
+ dm->state = DM_INITIALIZED;
+}
+
+static void balloon_onchannelcallback(void *context);
+
+static int dm_thread_func(void *dm_dev)
+{
+ struct hv_dynmem_device *dm = dm_dev;
+ int t;
+ unsigned long scan_start;
+
+ while (!kthread_should_stop()) {
+ t = wait_for_completion_timeout(&dm_device.config_event, 1*HZ);
+ /*
+ * The host expects us to post information on the memory
+ * pressure every second.
+ */
+
+ if (t == 0)
+ post_status(dm);
+
+ scan_start = jiffies;
+ switch (dm->state) {
+ case DM_BALLOON_UP:
+ balloon_up(dm, (struct dm_balloon *)recv_buffer);
+ break;
+
+ case DM_HOT_ADD:
+ hot_add_req(dm, (struct dm_hot_add *)recv_buffer);
+ break;
+ default:
+ break;
+ }
+
+ if (!time_in_range(jiffies, scan_start, scan_start + HZ))
+ post_status(dm);
+
+ }
+
+ return 0;
+}
+
+
+static void version_resp(struct hv_dynmem_device *dm,
+ struct dm_version_response *vresp)
+{
+ struct dm_version_request version_req;
+ int ret;
+
+ if (vresp->is_accepted) {
+ /*
+ * We are done; wakeup the
+ * context waiting for version
+ * negotiation.
+ */
+ complete(&dm->host_event);
+ return;
+ }
+ /*
+ * If there are more versions to try, continue
+ * with negotiations; if not
+ * shutdown the service since we are not able
+ * to negotiate a suitable version number
+ * with the host.
+ */
+ if (dm->next_version == 0)
+ goto version_error;
+
+ dm->next_version = 0;
+ memset(&version_req, 0, sizeof(struct dm_version_request));
+ version_req.hdr.type = DM_VERSION_REQUEST;
+ version_req.hdr.size = sizeof(struct dm_version_request);
+ version_req.hdr.trans_id = atomic_inc_return(&trans_id);
+ version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN7;
+ version_req.is_last_attempt = 1;
+
+ ret = vmbus_sendpacket(dm->dev->channel, &version_req,
+ sizeof(struct dm_version_request),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND, 0);
+
+ if (ret)
+ goto version_error;
+
+ return;
+
+version_error:
+ dm->state = DM_INIT_ERROR;
+ complete(&dm->host_event);
+}
+
+static void cap_resp(struct hv_dynmem_device *dm,
+ struct dm_capabilities_resp_msg *cap_resp)
+{
+ if (!cap_resp->is_accepted) {
+ pr_info("Capabilities not accepted by host\n");
+ dm->state = DM_INIT_ERROR;
+ }
+ complete(&dm->host_event);
+}
+
+static void balloon_onchannelcallback(void *context)
+{
+ struct hv_device *dev = context;
+ u32 recvlen;
+ u64 requestid;
+ struct dm_message *dm_msg;
+ struct dm_header *dm_hdr;
+ struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+
+ memset(recv_buffer, 0, sizeof(recv_buffer));
+ vmbus_recvpacket(dev->channel, recv_buffer,
+ PAGE_SIZE, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ dm_msg = (struct dm_message *)recv_buffer;
+ dm_hdr = &dm_msg->hdr;
+
+ switch (dm_hdr->type) {
+ case DM_VERSION_RESPONSE:
+ version_resp(dm,
+ (struct dm_version_response *)dm_msg);
+ break;
+
+ case DM_CAPABILITIES_RESPONSE:
+ cap_resp(dm,
+ (struct dm_capabilities_resp_msg *)dm_msg);
+ break;
+
+ case DM_BALLOON_REQUEST:
+ dm->state = DM_BALLOON_UP;
+ complete(&dm->config_event);
+ break;
+
+ case DM_UNBALLOON_REQUEST:
+ dm->state = DM_BALLOON_DOWN;
+ balloon_down(dm,
+ (struct dm_unballoon_request *)recv_buffer);
+ break;
+
+ case DM_MEM_HOT_ADD_REQUEST:
+ dm->state = DM_HOT_ADD;
+ complete(&dm->config_event);
+ break;
+
+ case DM_INFO_MESSAGE:
+ process_info(dm, (struct dm_info_msg *)dm_msg);
+ break;
+
+ default:
+ pr_err("Unhandled message: type: %d\n", dm_hdr->type);
+
+ }
+ }
+
+}
+
+static int balloon_probe(struct hv_device *dev,
+ const struct hv_vmbus_device_id *dev_id)
+{
+ int ret, t;
+ struct dm_version_request version_req;
+ struct dm_capabilities cap_msg;
+
+ do_hot_add = hot_add;
+
+ /*
+ * First allocate a send buffer.
+ */
+
+ send_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!send_buffer)
+ return -ENOMEM;
+
+ ret = vmbus_open(dev->channel, dm_ring_size, dm_ring_size, NULL, 0,
+ balloon_onchannelcallback, dev);
+
+ if (ret)
+ return ret;
+
+ dm_device.dev = dev;
+ dm_device.state = DM_INITIALIZING;
+ dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+ init_completion(&dm_device.host_event);
+ init_completion(&dm_device.config_event);
+
+ dm_device.thread =
+ kthread_run(dm_thread_func, &dm_device, "hv_balloon");
+ if (IS_ERR(dm_device.thread)) {
+ ret = PTR_ERR(dm_device.thread);
+ goto probe_error0;
+ }
+
+ hv_set_drvdata(dev, &dm_device);
+ /*
+ * Initiate the hand shake with the host and negotiate
+ * a version that the host can support. We start with the
+ * highest version number and go down if the host cannot
+ * support it.
+ */
+ memset(&version_req, 0, sizeof(struct dm_version_request));
+ version_req.hdr.type = DM_VERSION_REQUEST;
+ version_req.hdr.size = sizeof(struct dm_version_request);
+ version_req.hdr.trans_id = atomic_inc_return(&trans_id);
+ version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN8;
+ version_req.is_last_attempt = 0;
+
+ ret = vmbus_sendpacket(dev->channel, &version_req,
+ sizeof(struct dm_version_request),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ if (ret)
+ goto probe_error1;
+
+ t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
+ if (t == 0) {
+ ret = -ETIMEDOUT;
+ goto probe_error1;
+ }
+
+ /*
+ * If we could not negotiate a compatible version with the host
+ * fail the probe function.
+ */
+ if (dm_device.state == DM_INIT_ERROR) {
+ ret = -ETIMEDOUT;
+ goto probe_error1;
+ }
+ /*
+ * Now submit our capabilities to the host.
+ */
+ memset(&cap_msg, 0, sizeof(struct dm_capabilities));
+ cap_msg.hdr.type = DM_CAPABILITIES_REPORT;
+ cap_msg.hdr.size = sizeof(struct dm_capabilities);
+ cap_msg.hdr.trans_id = atomic_inc_return(&trans_id);
+
+ cap_msg.caps.cap_bits.balloon = 1;
+ /*
+ * While we currently don't support hot-add,
+ * we still advertise this capability since the
+ * host requires that guests partcipating in the
+ * dynamic memory protocol support hot add.
+ */
+ cap_msg.caps.cap_bits.hot_add = 1;
+
+ /*
+ * Currently the host does not use these
+ * values and we set them to what is done in the
+ * Windows driver.
+ */
+ cap_msg.min_page_cnt = 0;
+ cap_msg.max_page_number = -1;
+
+ ret = vmbus_sendpacket(dev->channel, &cap_msg,
+ sizeof(struct dm_capabilities),
+ (unsigned long)NULL,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ if (ret)
+ goto probe_error1;
+
+ t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
+ if (t == 0) {
+ ret = -ETIMEDOUT;
+ goto probe_error1;
+ }
+
+ /*
+ * If the host does not like our capabilities,
+ * fail the probe function.
+ */
+ if (dm_device.state == DM_INIT_ERROR) {
+ ret = -ETIMEDOUT;
+ goto probe_error1;
+ }
+
+ dm_device.state = DM_INITIALIZED;
+
+ return 0;
+
+probe_error1:
+ kthread_stop(dm_device.thread);
+
+probe_error0:
+ vmbus_close(dev->channel);
+ return ret;
+}
+
+static int balloon_remove(struct hv_device *dev)
+{
+ struct hv_dynmem_device *dm = hv_get_drvdata(dev);
+
+ if (dm->num_pages_ballooned != 0)
+ pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
+
+ vmbus_close(dev->channel);
+ kthread_stop(dm->thread);
+
+ return 0;
+}
+
+static const struct hv_vmbus_device_id id_table[] = {
+ /* Dynamic Memory Class ID */
+ /* 525074DC-8985-46e2-8057-A307DC18A502 */
+ { VMBUS_DEVICE(0xdc, 0x74, 0x50, 0X52, 0x85, 0x89, 0xe2, 0x46,
+ 0x80, 0x57, 0xa3, 0x07, 0xdc, 0x18, 0xa5, 0x02)
+ },
+ { },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+static struct hv_driver balloon_drv = {
+ .name = "hv_balloon",
+ .id_table = id_table,
+ .probe = balloon_probe,
+ .remove = balloon_remove,
+};
+
+static int __init init_balloon_drv(void)
+{
+
+ return vmbus_driver_register(&balloon_drv);
+}
+
+static void exit_balloon_drv(void)
+{
+
+ vmbus_driver_unregister(&balloon_drv);
+}
+
+module_init(init_balloon_drv);
+module_exit(exit_balloon_drv);
+
+MODULE_DESCRIPTION("Hyper-V Balloon");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c4633de64465..4800d4c2a7b7 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -334,6 +334,16 @@ config SENSORS_DA9052_ADC
This driver can also be built as module. If so, the module
will be called da9052-hwmon.
+config SENSORS_DA9055
+ tristate "Dialog Semiconductor DA9055 ADC"
+ depends on MFD_DA9055
+ help
+ If you say yes here you get support for ADC on the Dialog
+ Semiconductor DA9055 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called da9055-hwmon.
+
config SENSORS_I5K_AMB
tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
depends on PCI
@@ -455,7 +465,7 @@ config SENSORS_HIH6130
config SENSORS_CORETEMP
tristate "Intel Core/Core2/Atom temperature sensor"
- depends on X86 && PCI
+ depends on X86
help
If you say yes here you get support for the temperature
sensor inside your CPU. Most of the family 6 CPUs
@@ -1106,11 +1116,12 @@ config SENSORS_ADS1015
will be called ads1015.
config SENSORS_ADS7828
- tristate "Texas Instruments ADS7828"
+ tristate "Texas Instruments ADS7828 and compatibles"
depends on I2C
help
- If you say yes here you get support for Texas Instruments ADS7828
- 12-bit 8-channel ADC device.
+ If you say yes here you get support for Texas Instruments ADS7828 and
+ ADS7830 8-channel A/D converters. ADS7828 resolution is 12-bit, while
+ it is 8-bit on ADS7830.
This driver can also be built as a module. If so, the module
will be called ads7828.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 8d5fcb5e8e9f..a930f0997d25 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
+obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
obj-$(CONFIG_SENSORS_DS620) += ds620.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 78b81793ddd9..6119ff8e8c87 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -478,7 +478,7 @@ static int abituguru_write(struct abituguru_data *data,
* alarm for sensor type X and then enabling the sensor as sensor type
* X, if we then get an alarm it is a sensor of type X.
*/
-static int __devinit
+static int
abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
u8 sensor_addr)
{
@@ -635,7 +635,7 @@ abituguru_detect_bank1_sensor_type_exit:
* read/write test would be feasible because of the reaction above, I've
* however opted to stay on the safe side.
*/
-static void __devinit
+static void
abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
{
int i;
@@ -691,7 +691,7 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
(int)data->bank2_sensors);
}
-static void __devinit
+static void
abituguru_detect_no_pwms(struct abituguru_data *data)
{
int i, j;
@@ -1264,7 +1264,7 @@ static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = {
SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
};
-static int __devinit abituguru_probe(struct platform_device *pdev)
+static int abituguru_probe(struct platform_device *pdev)
{
struct abituguru_data *data;
int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
@@ -1434,7 +1434,7 @@ abituguru_probe_error:
return res;
}
-static int __devexit abituguru_remove(struct platform_device *pdev)
+static int abituguru_remove(struct platform_device *pdev)
{
int i;
struct abituguru_data *data = platform_get_drvdata(pdev);
@@ -1545,7 +1545,7 @@ static struct platform_driver abituguru_driver = {
.pm = ABIT_UGURU_PM,
},
.probe = abituguru_probe,
- .remove = __devexit_p(abituguru_remove),
+ .remove = abituguru_remove,
};
static int __init abituguru_detect(void)
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index b174b8b2b4df..205327d33c4d 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -966,7 +966,7 @@ static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
};
-static int __devinit abituguru3_probe(struct platform_device *pdev)
+static int abituguru3_probe(struct platform_device *pdev)
{
const int no_sysfs_attr[3] = { 10, 8, 7 };
int sensor_index[3] = { 0, 1, 1 };
@@ -1072,7 +1072,7 @@ abituguru3_probe_error:
return res;
}
-static int __devexit abituguru3_remove(struct platform_device *pdev)
+static int abituguru3_remove(struct platform_device *pdev)
{
int i;
struct abituguru3_data *data = platform_get_drvdata(pdev);
@@ -1171,7 +1171,7 @@ static struct platform_driver abituguru3_driver = {
.pm = ABIT_UGURU3_PM
},
.probe = abituguru3_probe,
- .remove = __devexit_p(abituguru3_remove),
+ .remove = abituguru3_remove,
};
static int __init abituguru3_dmi_detect(void)
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index 37c01e72d699..a57584d28a40 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -107,7 +107,7 @@ static const struct attribute_group ad7314_group = {
.attrs = ad7314_attributes,
};
-static int __devinit ad7314_probe(struct spi_device *spi_dev)
+static int ad7314_probe(struct spi_device *spi_dev)
{
int ret;
struct ad7314_data *chip;
@@ -135,7 +135,7 @@ error_remove_group:
return ret;
}
-static int __devexit ad7314_remove(struct spi_device *spi_dev)
+static int ad7314_remove(struct spi_device *spi_dev)
{
struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
@@ -159,7 +159,7 @@ static struct spi_driver ad7314_driver = {
.owner = THIS_MODULE,
},
.probe = ad7314_probe,
- .remove = __devexit_p(ad7314_remove),
+ .remove = ad7314_remove,
.id_table = ad7314_id,
};
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index b420fb3f3a71..f3a5d4764eb9 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -226,7 +226,7 @@ exit_remove:
return err;
}
-static int __devexit ad7414_remove(struct i2c_client *client)
+static int ad7414_remove(struct i2c_client *client)
{
struct ad7414_data *data = i2c_get_clientdata(client);
@@ -246,7 +246,7 @@ static struct i2c_driver ad7414_driver = {
.name = "ad7414",
},
.probe = ad7414_probe,
- .remove = __devexit_p(ad7414_remove),
+ .remove = ad7414_remove,
.id_table = ad7414_id,
};
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index f4c5867170d6..751b1f0264a4 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -161,7 +161,7 @@ static struct sensor_device_attribute ad_input[] = {
/*----------------------------------------------------------------------*/
-static int __devinit adcxx_probe(struct spi_device *spi)
+static int adcxx_probe(struct spi_device *spi)
{
int channels = spi_get_device_id(spi)->driver_data;
struct adcxx *adc;
@@ -208,7 +208,7 @@ out_err:
return status;
}
-static int __devexit adcxx_remove(struct spi_device *spi)
+static int adcxx_remove(struct spi_device *spi)
{
struct adcxx *adc = spi_get_drvdata(spi);
int i;
@@ -240,7 +240,7 @@ static struct spi_driver adcxx_driver = {
},
.id_table = adcxx_ids,
.probe = adcxx_probe,
- .remove = __devexit_p(adcxx_remove),
+ .remove = adcxx_remove,
};
module_spi_driver(adcxx_driver);
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 1f9e8af0f322..409b5c16defb 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -1,12 +1,14 @@
/*
- * ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC
+ * ads7828.c - driver for TI ADS7828 8-channel A/D converter and compatibles
* (C) 2007 EADS Astrium
*
* This driver is based on the lm75 and other lm_sensors/hwmon drivers
*
* Written by Steve Hardy <shardy@redhat.com>
*
- * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf
+ * ADS7830 support, by Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 file.
*
* 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
@@ -23,63 +25,48 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
+#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/platform_data/ads7828.h>
+#include <linux/slab.h>
/* The ADS7828 registers */
-#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */
-#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
-#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */
-#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */
-#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */
-#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */
-#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */
-#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
- I2C_CLIENT_END };
-
-/* Module parameters */
-static bool se_input = 1; /* Default is SE, 0 == diff */
-static bool int_vref = 1; /* Default is internal ref ON */
-static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */
-module_param(se_input, bool, S_IRUGO);
-module_param(int_vref, bool, S_IRUGO);
-module_param(vref_mv, int, S_IRUGO);
-
-/* Global Variables */
-static u8 ads7828_cmd_byte; /* cmd byte without channel bits */
-static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */
-
-/* Each client has this additional data */
+#define ADS7828_NCH 8 /* 8 channels supported */
+#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
+#define ADS7828_CMD_PD1 0x04 /* Internal vref OFF && A/D ON */
+#define ADS7828_CMD_PD3 0x0C /* Internal vref ON && A/D ON */
+#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */
+#define ADS7828_EXT_VREF_MV_MIN 50 /* External vref min value 0.05V */
+#define ADS7828_EXT_VREF_MV_MAX 5250 /* External vref max value 5.25V */
+
+/* List of supported devices */
+enum ads7828_chips { ads7828, ads7830 };
+
+/* Client specific data */
struct ads7828_data {
struct device *hwmon_dev;
- struct mutex update_lock; /* mutex protect updates */
- char valid; /* !=0 if following fields are valid */
- unsigned long last_updated; /* In jiffies */
- u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */
+ struct mutex update_lock; /* Mutex protecting updates */
+ unsigned long last_updated; /* Last updated time (in jiffies) */
+ u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH samples */
+ bool valid; /* Validity flag */
+ bool diff_input; /* Differential input */
+ bool ext_vref; /* External voltage reference */
+ unsigned int vref_mv; /* voltage reference value */
+ u8 cmd_byte; /* Command byte without channel bits */
+ unsigned int lsb_resol; /* Resolution of the ADC sample LSB */
+ s32 (*read_channel)(const struct i2c_client *client, u8 command);
};
-/* Function declaration - necessary due to function dependencies */
-static int ads7828_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int ads7828_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-
-static inline u8 channel_cmd_byte(int ch)
+/* Command byte C2,C1,C0 - see datasheet */
+static inline u8 ads7828_cmd_byte(u8 cmd, int ch)
{
- /* cmd byte C2,C1,C0 - see datasheet */
- u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4);
- cmd |= ads7828_cmd_byte;
- return cmd;
+ return cmd | (((ch >> 1) | (ch & 0x01) << 2) << 4);
}
/* Update data for the device (all 8 channels) */
@@ -96,12 +83,11 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
dev_dbg(&client->dev, "Starting ads7828 update\n");
for (ch = 0; ch < ADS7828_NCH; ch++) {
- u8 cmd = channel_cmd_byte(ch);
- data->adc_input[ch] =
- i2c_smbus_read_word_swapped(client, cmd);
+ u8 cmd = ads7828_cmd_byte(data->cmd_byte, ch);
+ data->adc_input[ch] = data->read_channel(client, cmd);
}
data->last_updated = jiffies;
- data->valid = 1;
+ data->valid = true;
}
mutex_unlock(&data->update_lock);
@@ -110,28 +96,25 @@ static struct ads7828_data *ads7828_update_device(struct device *dev)
}
/* sysfs callback function */
-static ssize_t show_in(struct device *dev, struct device_attribute *da,
- char *buf)
+static ssize_t ads7828_show_in(struct device *dev, struct device_attribute *da,
+ char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ads7828_data *data = ads7828_update_device(dev);
- /* Print value (in mV as specified in sysfs-interface documentation) */
- return sprintf(buf, "%d\n", (data->adc_input[attr->index] *
- ads7828_lsb_resol)/1000);
-}
+ unsigned int value = DIV_ROUND_CLOSEST(data->adc_input[attr->index] *
+ data->lsb_resol, 1000);
-#define in_reg(offset)\
-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\
- NULL, offset)
+ return sprintf(buf, "%d\n", value);
+}
-in_reg(0);
-in_reg(1);
-in_reg(2);
-in_reg(3);
-in_reg(4);
-in_reg(5);
-in_reg(6);
-in_reg(7);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ads7828_show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ads7828_show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ads7828_show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ads7828_show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ads7828_show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ads7828_show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7);
static struct attribute *ads7828_attributes[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
@@ -152,60 +135,9 @@ static const struct attribute_group ads7828_group = {
static int ads7828_remove(struct i2c_client *client)
{
struct ads7828_data *data = i2c_get_clientdata(client);
+
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &ads7828_group);
- return 0;
-}
-
-static const struct i2c_device_id ads7828_id[] = {
- { "ads7828", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, ads7828_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver ads7828_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "ads7828",
- },
- .probe = ads7828_probe,
- .remove = ads7828_remove,
- .id_table = ads7828_id,
- .detect = ads7828_detect,
- .address_list = normal_i2c,
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int ads7828_detect(struct i2c_client *client,
- struct i2c_board_info *info)
-{
- struct i2c_adapter *adapter = client->adapter;
- int ch;
-
- /* Check we have a valid client */
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
- return -ENODEV;
-
- /*
- * Now, we do the remaining detection. There is no identification
- * dedicated register so attempt to sanity check using knowledge of
- * the chip
- * - Read from the 8 channel addresses
- * - Check the top 4 bits of each result are not set (12 data bits)
- */
- for (ch = 0; ch < ADS7828_NCH; ch++) {
- u16 in_data;
- u8 cmd = channel_cmd_byte(ch);
- in_data = i2c_smbus_read_word_swapped(client, cmd);
- if (in_data & 0xF000) {
- pr_debug("%s : Doesn't look like an ads7828 device\n",
- __func__);
- return -ENODEV;
- }
- }
-
- strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
return 0;
}
@@ -213,6 +145,7 @@ static int ads7828_detect(struct i2c_client *client,
static int ads7828_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct ads7828_platform_data *pdata = client->dev.platform_data;
struct ads7828_data *data;
int err;
@@ -221,10 +154,37 @@ static int ads7828_probe(struct i2c_client *client,
if (!data)
return -ENOMEM;
+ if (pdata) {
+ data->diff_input = pdata->diff_input;
+ data->ext_vref = pdata->ext_vref;
+ if (data->ext_vref)
+ data->vref_mv = pdata->vref_mv;
+ }
+
+ /* Bound Vref with min/max values if it was provided */
+ if (data->vref_mv)
+ data->vref_mv = SENSORS_LIMIT(data->vref_mv,
+ ADS7828_EXT_VREF_MV_MIN,
+ ADS7828_EXT_VREF_MV_MAX);
+ else
+ data->vref_mv = ADS7828_INT_VREF_MV;
+
+ /* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */
+ if (id->driver_data == ads7828) {
+ data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 4096);
+ data->read_channel = i2c_smbus_read_word_swapped;
+ } else {
+ data->lsb_resol = DIV_ROUND_CLOSEST(data->vref_mv * 1000, 256);
+ data->read_channel = i2c_smbus_read_byte_data;
+ }
+
+ data->cmd_byte = data->ext_vref ? ADS7828_CMD_PD1 : ADS7828_CMD_PD3;
+ if (!data->diff_input)
+ data->cmd_byte |= ADS7828_CMD_SD_SE;
+
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- /* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
if (err)
return err;
@@ -232,38 +192,35 @@ static int ads7828_probe(struct i2c_client *client,
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
+ goto error;
}
return 0;
-exit_remove:
+error:
sysfs_remove_group(&client->dev.kobj, &ads7828_group);
return err;
}
-static int __init sensors_ads7828_init(void)
-{
- /* Initialize the command byte according to module parameters */
- ads7828_cmd_byte = se_input ?
- ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF;
- ads7828_cmd_byte |= int_vref ?
- ADS7828_CMD_PD3 : ADS7828_CMD_PD1;
+static const struct i2c_device_id ads7828_device_ids[] = {
+ { "ads7828", ads7828 },
+ { "ads7830", ads7830 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ads7828_device_ids);
- /* Calculate the LSB resolution */
- ads7828_lsb_resol = (vref_mv*1000)/4096;
+static struct i2c_driver ads7828_driver = {
+ .driver = {
+ .name = "ads7828",
+ },
- return i2c_add_driver(&ads7828_driver);
-}
+ .id_table = ads7828_device_ids,
+ .probe = ads7828_probe,
+ .remove = ads7828_remove,
+};
-static void __exit sensors_ads7828_exit(void)
-{
- i2c_del_driver(&ads7828_driver);
-}
+module_i2c_driver(ads7828_driver);
-MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
-MODULE_DESCRIPTION("ADS7828 driver");
MODULE_LICENSE("GPL");
-
-module_init(sensors_ads7828_init);
-module_exit(sensors_ads7828_exit);
+MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>");
+MODULE_DESCRIPTION("Driver for TI ADS7828 A/D converter and compatibles");
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 1b53aa42b6db..a79875986f91 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -173,7 +173,7 @@ static const struct attribute_group ads7871_group = {
.attrs = ads7871_attributes,
};
-static int __devinit ads7871_probe(struct spi_device *spi)
+static int ads7871_probe(struct spi_device *spi)
{
int ret, err;
uint8_t val;
@@ -225,7 +225,7 @@ error_remove:
return err;
}
-static int __devexit ads7871_remove(struct spi_device *spi)
+static int ads7871_remove(struct spi_device *spi)
{
struct ads7871_data *pdata = spi_get_drvdata(spi);
@@ -241,7 +241,7 @@ static struct spi_driver ads7871_driver = {
},
.probe = ads7871_probe,
- .remove = __devexit_p(ads7871_remove),
+ .remove = ads7871_remove,
};
module_spi_driver(ads7871_driver);
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 517f1856c706..34ff03abb50b 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -276,7 +276,7 @@ static int adt7411_detect(struct i2c_client *client,
return 0;
}
-static int __devinit adt7411_probe(struct i2c_client *client,
+static int adt7411_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adt7411_data *data;
@@ -317,7 +317,7 @@ static int __devinit adt7411_probe(struct i2c_client *client,
return ret;
}
-static int __devexit adt7411_remove(struct i2c_client *client)
+static int adt7411_remove(struct i2c_client *client)
{
struct adt7411_data *data = i2c_get_clientdata(client);
@@ -337,7 +337,7 @@ static struct i2c_driver adt7411_driver = {
.name = "adt7411",
},
.probe = adt7411_probe,
- .remove = __devexit_p(adt7411_remove),
+ .remove = adt7411_remove,
.id_table = adt7411_id,
.detect = adt7411_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 47b8d84b489d..d64923d63537 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -34,7 +34,6 @@
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/cpu.h>
-#include <linux/pci.h>
#include <linux/smp.h>
#include <linux/moduleparam.h>
#include <asm/msr.h>
@@ -197,14 +196,6 @@ struct tjmax {
};
static const struct tjmax __cpuinitconst tjmax_table[] = {
- { "CPU D410", 100000 },
- { "CPU D425", 100000 },
- { "CPU D510", 100000 },
- { "CPU D525", 100000 },
- { "CPU N450", 100000 },
- { "CPU N455", 100000 },
- { "CPU N470", 100000 },
- { "CPU N475", 100000 },
{ "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */
{ "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */
{ "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 */
@@ -212,6 +203,28 @@ static const struct tjmax __cpuinitconst tjmax_table[] = {
{ "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */
};
+struct tjmax_model {
+ u8 model;
+ u8 mask;
+ int tjmax;
+};
+
+#define ANY 0xff
+
+static const struct tjmax_model __cpuinitconst tjmax_model_table[] = {
+ { 0x1c, 10, 100000 }, /* D4xx, N4xx, D5xx, N5xx */
+ { 0x1c, ANY, 90000 }, /* Z5xx, N2xx, possibly others
+ * Note: Also matches 230 and 330,
+ * which are covered by tjmax_table
+ */
+ { 0x26, ANY, 90000 }, /* Atom Tunnel Creek (Exx), Lincroft (Z6xx)
+ * Note: TjMax for E6xxT is 110C, but CPU type
+ * is undetectable by software
+ */
+ { 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */
+ { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
+};
+
static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
struct device *dev)
{
@@ -222,7 +235,6 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
int usemsr_ee = 1;
int err;
u32 eax, edx;
- struct pci_dev *host_bridge;
int i;
/* explicit tjmax table entries override heuristics */
@@ -231,32 +243,18 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
return tjmax_table[i].tjmax;
}
+ for (i = 0; i < ARRAY_SIZE(tjmax_model_table); i++) {
+ const struct tjmax_model *tm = &tjmax_model_table[i];
+ if (c->x86_model == tm->model &&
+ (tm->mask == ANY || c->x86_mask == tm->mask))
+ return tm->tjmax;
+ }
+
/* Early chips have no MSR for TjMax */
if (c->x86_model == 0xf && c->x86_mask < 4)
usemsr_ee = 0;
- /* Atom CPUs */
-
- if (c->x86_model == 0x1c || c->x86_model == 0x26
- || c->x86_model == 0x27) {
- usemsr_ee = 0;
-
- host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
-
- if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
- && (host_bridge->device == 0xa000 /* NM10 based nettop */
- || host_bridge->device == 0xa010)) /* NM10 based netbook */
- tjmax = 100000;
- else
- tjmax = 90000;
-
- pci_dev_put(host_bridge);
- } else if (c->x86_model == 0x36) {
- usemsr_ee = 0;
- tjmax = 100000;
- }
-
if (c->x86_model > 0xe && usemsr_ee) {
u8 platform_id;
@@ -358,7 +356,7 @@ static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
return adjust_tjmax(c, id, dev);
}
-static int __devinit create_name_attr(struct platform_data *pdata,
+static int create_name_attr(struct platform_data *pdata,
struct device *dev)
{
sysfs_attr_init(&pdata->name_attr.attr);
@@ -553,7 +551,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
pdata->core_data[indx] = NULL;
}
-static int __devinit coretemp_probe(struct platform_device *pdev)
+static int coretemp_probe(struct platform_device *pdev)
{
struct platform_data *pdata;
int err;
@@ -586,7 +584,7 @@ exit_free:
return err;
}
-static int __devexit coretemp_remove(struct platform_device *pdev)
+static int coretemp_remove(struct platform_device *pdev)
{
struct platform_data *pdata = platform_get_drvdata(pdev);
int i;
@@ -608,7 +606,7 @@ static struct platform_driver coretemp_driver = {
.name = DRVNAME,
},
.probe = coretemp_probe,
- .remove = __devexit_p(coretemp_remove),
+ .remove = coretemp_remove,
};
static int __cpuinit coretemp_device_add(unsigned int cpu)
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
index b8d01c5f5713..ab4452c5a98c 100644
--- a/drivers/hwmon/da9052-hwmon.c
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -60,30 +60,17 @@ static inline int vbbat_reg_to_mV(int value)
return DIV_ROUND_CLOSEST(value * 2500, 512);
}
-static int da9052_enable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_enable_vddout_channel(struct da9052 *da9052)
{
- int ret;
-
- ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
- if (ret < 0)
- return ret;
-
- ret |= DA9052_ADCCONT_AUTOVDDEN;
-
- return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+ return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+ DA9052_ADCCONT_AUTOVDDEN,
+ DA9052_ADCCONT_AUTOVDDEN);
}
-static int da9052_disable_vddout_channel(struct da9052 *da9052)
+static inline int da9052_disable_vddout_channel(struct da9052 *da9052)
{
- int ret;
-
- ret = da9052_reg_read(da9052, DA9052_ADC_CONT_REG);
- if (ret < 0)
- return ret;
-
- ret &= ~DA9052_ADCCONT_AUTOVDDEN;
-
- return da9052_reg_write(da9052, DA9052_ADC_CONT_REG, ret);
+ return da9052_reg_update(da9052, DA9052_ADC_CONT_REG,
+ DA9052_ADCCONT_AUTOVDDEN, 0);
}
static ssize_t da9052_read_vddout(struct device *dev,
@@ -283,7 +270,7 @@ static struct attribute *da9052_attr[] = {
static const struct attribute_group da9052_attr_group = {.attrs = da9052_attr};
-static int __devinit da9052_hwmon_probe(struct platform_device *pdev)
+static int da9052_hwmon_probe(struct platform_device *pdev)
{
struct da9052_hwmon *hwmon;
int ret;
@@ -316,7 +303,7 @@ err_mem:
return ret;
}
-static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
+static int da9052_hwmon_remove(struct platform_device *pdev)
{
struct da9052_hwmon *hwmon = platform_get_drvdata(pdev);
@@ -328,7 +315,7 @@ static int __devexit da9052_hwmon_remove(struct platform_device *pdev)
static struct platform_driver da9052_hwmon_driver = {
.probe = da9052_hwmon_probe,
- .remove = __devexit_p(da9052_hwmon_remove),
+ .remove = da9052_hwmon_remove,
.driver = {
.name = "da9052-hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwmon/da9055-hwmon.c b/drivers/hwmon/da9055-hwmon.c
new file mode 100644
index 000000000000..9465c050c326
--- /dev/null
+++ b/drivers/hwmon/da9055-hwmon.c
@@ -0,0 +1,336 @@
+/*
+ * HWMON Driver for Dialog DA9055
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.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/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+
+#define DA9055_ADCIN_DIV 102
+#define DA9055_VSYS_DIV 85
+
+#define DA9055_ADC_VSYS 0
+#define DA9055_ADC_ADCIN1 1
+#define DA9055_ADC_ADCIN2 2
+#define DA9055_ADC_ADCIN3 3
+#define DA9055_ADC_TJUNC 4
+
+struct da9055_hwmon {
+ struct da9055 *da9055;
+ struct device *class_device;
+ struct mutex hwmon_lock;
+ struct mutex irq_lock;
+ struct completion done;
+};
+
+static const char * const input_names[] = {
+ [DA9055_ADC_VSYS] = "VSYS",
+ [DA9055_ADC_ADCIN1] = "ADC IN1",
+ [DA9055_ADC_ADCIN2] = "ADC IN2",
+ [DA9055_ADC_ADCIN3] = "ADC IN3",
+ [DA9055_ADC_TJUNC] = "CHIP TEMP",
+};
+
+static const u8 chan_mux[DA9055_ADC_TJUNC + 1] = {
+ [DA9055_ADC_VSYS] = DA9055_ADC_MUX_VSYS,
+ [DA9055_ADC_ADCIN1] = DA9055_ADC_MUX_ADCIN1,
+ [DA9055_ADC_ADCIN2] = DA9055_ADC_MUX_ADCIN2,
+ [DA9055_ADC_ADCIN3] = DA9055_ADC_MUX_ADCIN3,
+ [DA9055_ADC_TJUNC] = DA9055_ADC_MUX_T_SENSE,
+};
+
+static int da9055_adc_manual_read(struct da9055_hwmon *hwmon,
+ unsigned char channel)
+{
+ int ret;
+ unsigned short calc_data;
+ unsigned short data;
+ unsigned char mux_sel;
+ struct da9055 *da9055 = hwmon->da9055;
+
+ if (channel > DA9055_ADC_TJUNC)
+ return -EINVAL;
+
+ mutex_lock(&hwmon->irq_lock);
+
+ /* Selects desired MUX for manual conversion */
+ mux_sel = chan_mux[channel] | DA9055_ADC_MAN_CONV;
+
+ ret = da9055_reg_write(da9055, DA9055_REG_ADC_MAN, mux_sel);
+ if (ret < 0)
+ goto err;
+
+ /* Wait for an interrupt */
+ if (!wait_for_completion_timeout(&hwmon->done,
+ msecs_to_jiffies(500))) {
+ dev_err(da9055->dev,
+ "timeout waiting for ADC conversion interrupt\n");
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_H);
+ if (ret < 0)
+ goto err;
+
+ calc_data = (unsigned short)ret;
+ data = calc_data << 2;
+
+ ret = da9055_reg_read(da9055, DA9055_REG_ADC_RES_L);
+ if (ret < 0)
+ goto err;
+
+ calc_data = (unsigned short)(ret & DA9055_ADC_LSB_MASK);
+ data |= calc_data;
+
+ ret = data;
+
+err:
+ mutex_unlock(&hwmon->irq_lock);
+ return ret;
+}
+
+static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
+{
+ struct da9055_hwmon *hwmon = irq_data;
+
+ complete(&hwmon->done);
+
+ return IRQ_HANDLED;
+}
+
+/* Conversion function for VSYS and ADCINx */
+static inline int volt_reg_to_mV(int value, int channel)
+{
+ if (channel == DA9055_ADC_VSYS)
+ return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
+ else
+ return DIV_ROUND_CLOSEST(value * 1000, DA9055_ADCIN_DIV);
+}
+
+static int da9055_enable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+ return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel,
+ 1 << channel);
+
+}
+
+static int da9055_disable_auto_mode(struct da9055 *da9055, int channel)
+{
+
+ return da9055_reg_update(da9055, DA9055_REG_ADC_CONT, 1 << channel, 0);
+}
+
+static ssize_t da9055_read_auto_ch(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+ int ret, adc;
+ int channel = to_sensor_dev_attr(devattr)->index;
+
+ mutex_lock(&hwmon->hwmon_lock);
+
+ ret = da9055_enable_auto_mode(hwmon->da9055, channel);
+ if (ret < 0)
+ goto hwmon_err;
+
+ usleep_range(10000, 10500);
+
+ adc = da9055_reg_read(hwmon->da9055, DA9055_REG_VSYS_RES + channel);
+ if (adc < 0) {
+ ret = adc;
+ goto hwmon_err_release;
+ }
+
+ ret = da9055_disable_auto_mode(hwmon->da9055, channel);
+ if (ret < 0)
+ goto hwmon_err;
+
+ mutex_unlock(&hwmon->hwmon_lock);
+
+ return sprintf(buf, "%d\n", volt_reg_to_mV(adc, channel));
+
+hwmon_err_release:
+ da9055_disable_auto_mode(hwmon->da9055, channel);
+hwmon_err:
+ mutex_unlock(&hwmon->hwmon_lock);
+ return ret;
+}
+
+static ssize_t da9055_read_tjunc(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct da9055_hwmon *hwmon = dev_get_drvdata(dev);
+ int tjunc;
+ int toffset;
+
+ tjunc = da9055_adc_manual_read(hwmon, DA9055_ADC_TJUNC);
+ if (tjunc < 0)
+ return tjunc;
+
+ toffset = da9055_reg_read(hwmon->da9055, DA9055_REG_T_OFFSET);
+ if (toffset < 0)
+ return toffset;
+
+ /*
+ * Degrees celsius = -0.4084 * (ADC_RES - T_OFFSET) + 307.6332
+ * T_OFFSET is a trim value used to improve accuracy of the result
+ */
+ return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(-4084 * (tjunc - toffset)
+ + 3076332, 10000));
+}
+
+static ssize_t da9055_hwmon_show_name(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ return sprintf(buf, "da9055-hwmon\n");
+}
+
+static ssize_t show_label(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ return sprintf(buf, "%s\n",
+ input_names[to_sensor_dev_attr(devattr)->index]);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, da9055_read_auto_ch, NULL,
+ DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_label, NULL,
+ DA9055_ADC_VSYS);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, da9055_read_auto_ch, NULL,
+ DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_label, NULL,
+ DA9055_ADC_ADCIN1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, da9055_read_auto_ch, NULL,
+ DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_label, NULL,
+ DA9055_ADC_ADCIN2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, da9055_read_auto_ch, NULL,
+ DA9055_ADC_ADCIN3);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL,
+ DA9055_ADC_ADCIN3);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, da9055_read_tjunc, NULL,
+ DA9055_ADC_TJUNC);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL,
+ DA9055_ADC_TJUNC);
+
+static DEVICE_ATTR(name, S_IRUGO, da9055_hwmon_show_name, NULL);
+
+static struct attribute *da9055_attr[] = {
+ &dev_attr_name.attr,
+ &sensor_dev_attr_in0_input.dev_attr.attr,
+ &sensor_dev_attr_in0_label.dev_attr.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in1_label.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in2_label.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in3_label.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_label.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group da9055_attr_group = {.attrs = da9055_attr};
+
+static int da9055_hwmon_probe(struct platform_device *pdev)
+{
+ struct da9055_hwmon *hwmon;
+ int hwmon_irq, ret;
+
+ hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9055_hwmon),
+ GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ mutex_init(&hwmon->hwmon_lock);
+ mutex_init(&hwmon->irq_lock);
+
+ init_completion(&hwmon->done);
+ hwmon->da9055 = dev_get_drvdata(pdev->dev.parent);
+
+ platform_set_drvdata(pdev, hwmon);
+
+ hwmon_irq = platform_get_irq_byname(pdev, "HWMON");
+ if (hwmon_irq < 0)
+ return hwmon_irq;
+
+ hwmon_irq = regmap_irq_get_virq(hwmon->da9055->irq_data, hwmon_irq);
+ if (hwmon_irq < 0)
+ return hwmon_irq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, hwmon_irq,
+ NULL, da9055_auxadc_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "adc-irq", hwmon);
+ if (ret != 0) {
+ dev_err(hwmon->da9055->dev, "DA9055 ADC IRQ failed ret=%d\n",
+ ret);
+ return ret;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &da9055_attr_group);
+ if (ret)
+ return ret;
+
+ hwmon->class_device = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(hwmon->class_device)) {
+ ret = PTR_ERR(hwmon->class_device);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+ return ret;
+}
+
+static int da9055_hwmon_remove(struct platform_device *pdev)
+{
+ struct da9055_hwmon *hwmon = platform_get_drvdata(pdev);
+
+ sysfs_remove_group(&pdev->dev.kobj, &da9055_attr_group);
+ hwmon_device_unregister(hwmon->class_device);
+
+ return 0;
+}
+
+static struct platform_driver da9055_hwmon_driver = {
+ .probe = da9055_hwmon_probe,
+ .remove = da9055_hwmon_remove,
+ .driver = {
+ .name = "da9055-hwmon",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(da9055_hwmon_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("DA9055 HWMON driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-hwmon");
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index fe0eeec0b750..7430f70ae452 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2630,7 +2630,7 @@ exit:
return err;
}
-static int __devinit dme1737_isa_probe(struct platform_device *pdev)
+static int dme1737_isa_probe(struct platform_device *pdev)
{
u8 company, device;
struct resource *res;
@@ -2718,7 +2718,7 @@ exit_remove_files:
return err;
}
-static int __devexit dme1737_isa_remove(struct platform_device *pdev)
+static int dme1737_isa_remove(struct platform_device *pdev)
{
struct dme1737_data *data = platform_get_drvdata(pdev);
@@ -2734,7 +2734,7 @@ static struct platform_driver dme1737_isa_driver = {
.name = "dme1737",
},
.probe = dme1737_isa_probe,
- .remove = __devexit_p(dme1737_isa_remove),
+ .remove = dme1737_isa_remove,
};
/* ---------------------------------------------------------------------
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 4dd7723d257f..a9816979c5de 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -1343,7 +1343,7 @@ static struct attribute *f71805f_attr_pwm[] = {
* Device registration and initialization
*/
-static void __devinit f71805f_init_device(struct f71805f_data *data)
+static void f71805f_init_device(struct f71805f_data *data)
{
u8 reg;
int i;
@@ -1374,7 +1374,7 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
}
}
-static int __devinit f71805f_probe(struct platform_device *pdev)
+static int f71805f_probe(struct platform_device *pdev)
{
struct f71805f_sio_data *sio_data = pdev->dev.platform_data;
struct f71805f_data *data;
@@ -1490,7 +1490,7 @@ exit_remove_files:
return err;
}
-static int __devexit f71805f_remove(struct platform_device *pdev)
+static int f71805f_remove(struct platform_device *pdev)
{
struct f71805f_data *data = platform_get_drvdata(pdev);
int i;
@@ -1510,7 +1510,7 @@ static struct platform_driver f71805f_driver = {
.name = DRVNAME,
},
.probe = f71805f_probe,
- .remove = __devexit_p(f71805f_remove),
+ .remove = f71805f_remove,
};
static int __init f71805f_device_add(unsigned short address,
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 50e4ce2d22d8..bb7275cc47f3 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -364,7 +364,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
char *buf);
-static int __devinit f71882fg_probe(struct platform_device *pdev);
+static int f71882fg_probe(struct platform_device *pdev);
static int f71882fg_remove(struct platform_device *pdev);
static struct platform_driver f71882fg_driver = {
@@ -2145,7 +2145,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%s\n", f71882fg_names[data->type]);
}
-static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
+static int f71882fg_create_sysfs_files(struct platform_device *pdev,
struct sensor_device_attribute_2 *attr, int count)
{
int err, i;
@@ -2167,7 +2167,7 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
device_remove_file(&pdev->dev, &attr[i].dev_attr);
}
-static int __devinit f71882fg_create_fan_sysfs_files(
+static int f71882fg_create_fan_sysfs_files(
struct platform_device *pdev, int idx)
{
struct f71882fg_data *data = platform_get_drvdata(pdev);
@@ -2265,7 +2265,7 @@ static int __devinit f71882fg_create_fan_sysfs_files(
return err;
}
-static int __devinit f71882fg_probe(struct platform_device *pdev)
+static int f71882fg_probe(struct platform_device *pdev)
{
struct f71882fg_data *data;
struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 4f4110407387..b757088aeddb 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -31,6 +31,9 @@ MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
MODULE_LICENSE("GPL");
+/* Family 16h Northbridge's function 4 PCI ID */
+#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534
+
/* D18F3 */
#define REG_NORTHBRIDGE_CAP 0xe8
@@ -111,7 +114,7 @@ static const struct attribute_group fam15h_power_attr_group = {
.attrs = fam15h_power_attrs,
};
-static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
+static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
{
u32 val;
@@ -168,7 +171,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
#define fam15h_power_resume NULL
#endif
-static void __devinit fam15h_power_init_data(struct pci_dev *f4,
+static void fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data)
{
u32 val;
@@ -194,7 +197,7 @@ static void __devinit fam15h_power_init_data(struct pci_dev *f4,
data->processor_pwr_watts = (tmp * 15625) >> 10;
}
-static int __devinit fam15h_power_probe(struct pci_dev *pdev,
+static int fam15h_power_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct fam15h_power_data *data;
@@ -235,7 +238,7 @@ exit_remove_group:
return err;
}
-static void __devexit fam15h_power_remove(struct pci_dev *pdev)
+static void fam15h_power_remove(struct pci_dev *pdev)
{
struct device *dev;
struct fam15h_power_data *data;
@@ -248,6 +251,7 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
{}
};
MODULE_DEVICE_TABLE(pci, fam15h_power_id_table);
@@ -256,7 +260,7 @@ static struct pci_driver fam15h_power_driver = {
.name = "fam15h_power",
.id_table = fam15h_power_id_table,
.probe = fam15h_power_probe,
- .remove = __devexit_p(fam15h_power_remove),
+ .remove = fam15h_power_remove,
.resume = fam15h_power_resume,
};
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 1381a2e3bbd4..4e04c1228e51 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -499,13 +499,13 @@ static int gpio_fan_get_of_pdata(struct device *dev,
return 0;
}
-static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+static struct of_device_id of_gpio_fan_match[] = {
{ .compatible = "gpio-fan", },
{},
};
#endif /* CONFIG_OF_GPIO */
-static int __devinit gpio_fan_probe(struct platform_device *pdev)
+static int gpio_fan_probe(struct platform_device *pdev)
{
int err;
struct gpio_fan_data *fan_data;
@@ -581,7 +581,7 @@ err_free_alarm:
return err;
}
-static int __devexit gpio_fan_remove(struct platform_device *pdev)
+static int gpio_fan_remove(struct platform_device *pdev)
{
struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
@@ -626,7 +626,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
static struct platform_driver gpio_fan_driver = {
.probe = gpio_fan_probe,
- .remove = __devexit_p(gpio_fan_remove),
+ .remove = gpio_fan_remove,
.driver = {
.name = "gpio-fan",
.pm = GPIO_FAN_PM,
diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c
index 9a675efaa78d..2dc37c7c6947 100644
--- a/drivers/hwmon/hih6130.c
+++ b/drivers/hwmon/hih6130.c
@@ -220,7 +220,7 @@ static const struct attribute_group hih6130_attr_group = {
* device's name.
* Returns 0 on success.
*/
-static int __devinit hih6130_probe(struct i2c_client *client,
+static int hih6130_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct hih6130 *hih6130;
@@ -263,7 +263,7 @@ fail_remove_sysfs:
* hih6130_remove() - remove device
* @client: I2C client device
*/
-static int __devexit hih6130_remove(struct i2c_client *client)
+static int hih6130_remove(struct i2c_client *client)
{
struct hih6130 *hih6130 = i2c_get_clientdata(client);
@@ -283,7 +283,7 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id);
static struct i2c_driver hih6130_driver = {
.driver.name = "hih6130",
.probe = hih6130_probe,
- .remove = __devexit_p(hih6130_remove),
+ .remove = hih6130_remove,
.id_table = hih6130_id,
};
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 46141abaafba..b87c2ccee06b 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -260,7 +260,7 @@ static ssize_t show_label(struct device *dev,
attr->index & DIMM_MASK);
}
-static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+static int i5k_amb_hwmon_init(struct platform_device *pdev)
{
int i, j, k, d = 0;
u16 c;
@@ -406,7 +406,7 @@ exit_remove:
return res;
}
-static int __devinit i5k_amb_add(void)
+static int i5k_amb_add(void)
{
int res = -ENODEV;
@@ -425,7 +425,7 @@ err:
return res;
}
-static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
+static int i5k_find_amb_registers(struct i5k_amb_data *data,
unsigned long devid)
{
struct pci_dev *pcidev;
@@ -459,7 +459,7 @@ out:
return res;
}
-static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+static int i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
{
struct pci_dev *pcidev;
u16 val16;
@@ -488,14 +488,14 @@ out:
static struct {
unsigned long err;
unsigned long fbd0;
-} chipset_ids[] __devinitdata = {
+} chipset_ids[] = {
{ PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 },
{ PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 },
{ 0, 0 }
};
#ifdef MODULE
-static struct pci_device_id i5k_amb_ids[] __devinitdata = {
+static struct pci_device_id i5k_amb_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
{ 0, }
@@ -503,7 +503,7 @@ static struct pci_device_id i5k_amb_ids[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
#endif
-static int __devinit i5k_amb_probe(struct platform_device *pdev)
+static int i5k_amb_probe(struct platform_device *pdev)
{
struct i5k_amb_data *data;
struct resource *reso;
@@ -564,7 +564,7 @@ err:
return res;
}
-static int __devexit i5k_amb_remove(struct platform_device *pdev)
+static int i5k_amb_remove(struct platform_device *pdev)
{
int i;
struct i5k_amb_data *data = platform_get_drvdata(pdev);
@@ -587,7 +587,7 @@ static struct platform_driver i5k_amb_driver = {
.name = DRVNAME,
},
.probe = i5k_amb_probe,
- .remove = __devexit_p(i5k_amb_remove),
+ .remove = i5k_amb_remove,
};
static int __init i5k_amb_init(void)
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 2b726346f8fa..8e7158c3ad2f 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -302,19 +302,8 @@ static struct i2c_driver ina2xx_driver = {
.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_i2c_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 f1de3979181f..d32aa354cbdf 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -428,7 +428,7 @@ static inline int has_old_autopwm(const struct it87_data *data)
}
static int it87_probe(struct platform_device *pdev);
-static int __devexit it87_remove(struct platform_device *pdev);
+static int it87_remove(struct platform_device *pdev);
static int it87_read_value(struct it87_data *data, u8 reg);
static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
@@ -443,7 +443,7 @@ static struct platform_driver it87_driver = {
.name = DRVNAME,
},
.probe = it87_probe,
- .remove = __devexit_p(it87_remove),
+ .remove = it87_remove,
};
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
@@ -1966,7 +1966,7 @@ static void it87_remove_files(struct device *dev)
sysfs_remove_group(&dev->kobj, &it87_group_label);
}
-static int __devinit it87_probe(struct platform_device *pdev)
+static int it87_probe(struct platform_device *pdev)
{
struct it87_data *data;
struct resource *res;
@@ -2158,7 +2158,7 @@ error:
return err;
}
-static int __devexit it87_remove(struct platform_device *pdev)
+static int it87_remove(struct platform_device *pdev)
{
struct it87_data *data = platform_get_drvdata(pdev);
@@ -2191,7 +2191,7 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
}
/* Return 1 if and only if the PWM interface is safe to use */
-static int __devinit it87_check_pwm(struct device *dev)
+static int it87_check_pwm(struct device *dev)
{
struct it87_data *data = dev_get_drvdata(dev);
/*
@@ -2248,7 +2248,7 @@ static int __devinit it87_check_pwm(struct device *dev)
}
/* Called when we have found a new IT87. */
-static void __devinit it87_init_device(struct platform_device *pdev)
+static void it87_init_device(struct platform_device *pdev)
{
struct it87_sio_data *sio_data = pdev->dev.platform_data;
struct it87_data *data = platform_get_drvdata(pdev);
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
index dee9eec2036e..e0d66b9590ab 100644
--- a/drivers/hwmon/jz4740-hwmon.c
+++ b/drivers/hwmon/jz4740-hwmon.c
@@ -102,7 +102,7 @@ static const struct attribute_group jz4740_hwmon_attr_group = {
.attrs = jz4740_hwmon_attributes,
};
-static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
+static int jz4740_hwmon_probe(struct platform_device *pdev)
{
int ret;
struct jz4740_hwmon *hwmon;
@@ -172,7 +172,7 @@ err_remove_file:
return ret;
}
-static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
+static int jz4740_hwmon_remove(struct platform_device *pdev)
{
struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev);
@@ -184,7 +184,7 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
static struct platform_driver jz4740_hwmon_driver = {
.probe = jz4740_hwmon_probe,
- .remove = __devexit_p(jz4740_hwmon_remove),
+ .remove = jz4740_hwmon_remove,
.driver = {
.name = "jz4740-hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index f2fe8078633b..e3b037c73a7e 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -95,7 +95,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-static bool __devinit has_erratum_319(struct pci_dev *pdev)
+static bool has_erratum_319(struct pci_dev *pdev)
{
u32 pkg_type, reg_dram_cfg;
@@ -129,7 +129,7 @@ static bool __devinit has_erratum_319(struct pci_dev *pdev)
(boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
}
-static int __devinit k10temp_probe(struct pci_dev *pdev,
+static int k10temp_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct device *hwmon_dev;
@@ -192,7 +192,7 @@ exit:
return err;
}
-static void __devexit k10temp_remove(struct pci_dev *pdev)
+static void k10temp_remove(struct pci_dev *pdev)
{
hwmon_device_unregister(pci_get_drvdata(pdev));
device_remove_file(&pdev->dev, &dev_attr_name);
@@ -219,7 +219,7 @@ static struct pci_driver k10temp_driver = {
.name = "k10temp",
.id_table = k10temp_id_table,
.probe = k10temp_probe,
- .remove = __devexit_p(k10temp_remove),
+ .remove = k10temp_remove,
};
module_pci_driver(k10temp_driver);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index e8c7fb0bbf95..9f3c0aeacdb9 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -142,7 +142,7 @@ static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
MODULE_DEVICE_TABLE(pci, k8temp_ids);
-static int __devinit is_rev_g_desktop(u8 model)
+static int is_rev_g_desktop(u8 model)
{
u32 brandidx;
@@ -173,7 +173,7 @@ static int __devinit is_rev_g_desktop(u8 model)
return 1;
}
-static int __devinit k8temp_probe(struct pci_dev *pdev,
+static int k8temp_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int err;
@@ -304,7 +304,7 @@ exit_remove:
return err;
}
-static void __devexit k8temp_remove(struct pci_dev *pdev)
+static void k8temp_remove(struct pci_dev *pdev)
{
struct k8temp_data *data = pci_get_drvdata(pdev);
@@ -324,7 +324,7 @@ static struct pci_driver k8temp_driver = {
.name = "k8temp",
.id_table = k8temp_ids,
.probe = k8temp_probe,
- .remove = __devexit_p(k8temp_remove),
+ .remove = k8temp_remove,
};
module_pci_driver(k8temp_driver);
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 2d1777a03edb..016efa26ba7c 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -131,7 +131,7 @@ static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
/*----------------------------------------------------------------------*/
-static int __devinit lm70_probe(struct spi_device *spi)
+static int lm70_probe(struct spi_device *spi)
{
int chip = spi_get_device_id(spi)->driver_data;
struct lm70 *p_lm70;
@@ -178,7 +178,7 @@ out_dev_create_temp_file_failed:
return status;
}
-static int __devexit lm70_remove(struct spi_device *spi)
+static int lm70_remove(struct spi_device *spi)
{
struct lm70 *p_lm70 = spi_get_drvdata(spi);
@@ -207,7 +207,7 @@ static struct spi_driver lm70_driver = {
},
.id_table = lm70_ids,
.probe = lm70_probe,
- .remove = __devexit_p(lm70_remove),
+ .remove = lm70_remove,
};
module_spi_driver(lm70_driver);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index c6ffafe600ad..53d6ee8ffa33 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -833,7 +833,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
}
#ifdef CONFIG_ISA
-static int __devinit lm78_isa_probe(struct platform_device *pdev)
+static int lm78_isa_probe(struct platform_device *pdev)
{
int err;
struct lm78_data *data;
@@ -886,7 +886,7 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
return err;
}
-static int __devexit lm78_isa_remove(struct platform_device *pdev)
+static int lm78_isa_remove(struct platform_device *pdev)
{
struct lm78_data *data = platform_get_drvdata(pdev);
@@ -903,7 +903,7 @@ static struct platform_driver lm78_isa_driver = {
.name = "lm78",
},
.probe = lm78_isa_probe,
- .remove = __devexit_p(lm78_isa_remove),
+ .remove = lm78_isa_remove,
};
/* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index b4eb0889c465..eda077de8a9f 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -157,7 +157,7 @@ static const struct attribute_group max1110_attr_group = {
.attrs = max1110_attributes,
};
-static int __devinit setup_transfer(struct max1111_data *data)
+static int setup_transfer(struct max1111_data *data)
{
struct spi_message *m;
struct spi_transfer *x;
@@ -179,7 +179,7 @@ static int __devinit setup_transfer(struct max1111_data *data)
return 0;
}
-static int __devinit max1111_probe(struct spi_device *spi)
+static int max1111_probe(struct spi_device *spi)
{
enum chips chip = spi_get_device_id(spi)->driver_data;
struct max1111_data *data;
@@ -256,7 +256,7 @@ err_remove:
return err;
}
-static int __devexit max1111_remove(struct spi_device *spi)
+static int max1111_remove(struct spi_device *spi)
{
struct max1111_data *data = spi_get_drvdata(spi);
@@ -283,7 +283,7 @@ static struct spi_driver max1111_driver = {
},
.id_table = max1111_ids,
.probe = max1111_probe,
- .remove = __devexit_p(max1111_remove),
+ .remove = max1111_remove,
};
module_spi_driver(max1111_driver);
diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
index 6304f2616fa7..b5ebb9198c75 100644
--- a/drivers/hwmon/max197.c
+++ b/drivers/hwmon/max197.c
@@ -257,7 +257,7 @@ static const struct attribute_group max197_sysfs_group = {
},
};
-static int __devinit max197_probe(struct platform_device *pdev)
+static int max197_probe(struct platform_device *pdev)
{
int ch, ret;
struct max197_data *data;
@@ -316,7 +316,7 @@ error:
return ret;
}
-static int __devexit max197_remove(struct platform_device *pdev)
+static int max197_remove(struct platform_device *pdev)
{
struct max197_data *data = platform_get_drvdata(pdev);
@@ -339,7 +339,7 @@ static struct platform_driver max197_driver = {
.owner = THIS_MODULE,
},
.probe = max197_probe,
- .remove = __devexit_p(max197_remove),
+ .remove = max197_remove,
.id_table = max197_device_ids,
};
module_platform_driver(max197_driver);
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index cf47a59657a9..2a7f331cd3c0 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -233,7 +233,7 @@ out_err_create_16chans:
return ret;
}
-static int __devexit mc13783_adc_remove(struct platform_device *pdev)
+static int mc13783_adc_remove(struct platform_device *pdev)
{
struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data;
@@ -265,7 +265,7 @@ static const struct platform_device_id mc13783_adc_idtable[] = {
MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable);
static struct platform_driver mc13783_adc_driver = {
- .remove = __devexit_p(mc13783_adc_remove),
+ .remove = mc13783_adc_remove,
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 74a6c58d0218..a87eb8986e36 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -309,7 +309,7 @@ static const struct attribute_group ntc_attr_group = {
.attrs = ntc_attributes,
};
-static int __devinit ntc_thermistor_probe(struct platform_device *pdev)
+static int ntc_thermistor_probe(struct platform_device *pdev)
{
struct ntc_data *data;
struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
@@ -393,7 +393,7 @@ err_after_sysfs:
return ret;
}
-static int __devexit ntc_thermistor_remove(struct platform_device *pdev)
+static int ntc_thermistor_remove(struct platform_device *pdev)
{
struct ntc_data *data = platform_get_drvdata(pdev);
@@ -419,7 +419,7 @@ static struct platform_driver ntc_thermistor_driver = {
.owner = THIS_MODULE,
},
.probe = ntc_thermistor_probe,
- .remove = __devexit_p(ntc_thermistor_remove),
+ .remove = ntc_thermistor_remove,
.id_table = ntc_thermistor_id,
};
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 91d5b2a21dd9..e35856bb79b4 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -228,7 +228,7 @@ struct pc87360_data {
*/
static int pc87360_probe(struct platform_device *pdev);
-static int __devexit pc87360_remove(struct platform_device *pdev);
+static int pc87360_remove(struct platform_device *pdev);
static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
u8 reg);
@@ -248,7 +248,7 @@ static struct platform_driver pc87360_driver = {
.name = "pc87360",
},
.probe = pc87360_probe,
- .remove = __devexit_p(pc87360_remove),
+ .remove = pc87360_remove,
};
/*
@@ -1221,7 +1221,7 @@ static void pc87360_remove_files(struct device *dev)
sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
}
-static int __devinit pc87360_probe(struct platform_device *pdev)
+static int pc87360_probe(struct platform_device *pdev)
{
int i;
struct pc87360_data *data;
@@ -1375,7 +1375,7 @@ error:
return err;
}
-static int __devexit pc87360_remove(struct platform_device *pdev)
+static int pc87360_remove(struct platform_device *pdev)
{
struct pc87360_data *data = platform_get_drvdata(pdev);
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index f185b1fa53e5..6086ad039d7d 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -956,7 +956,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
* Device detection, attach and detach
*/
-static int __devinit pc87427_request_regions(struct platform_device *pdev,
+static int pc87427_request_regions(struct platform_device *pdev,
int count)
{
struct resource *res;
@@ -980,7 +980,7 @@ static int __devinit pc87427_request_regions(struct platform_device *pdev,
return 0;
}
-static void __devinit pc87427_init_device(struct device *dev)
+static void pc87427_init_device(struct device *dev)
{
struct pc87427_sio_data *sio_data = dev->platform_data;
struct pc87427_data *data = dev_get_drvdata(dev);
@@ -1072,7 +1072,7 @@ static void pc87427_remove_files(struct device *dev)
}
}
-static int __devinit pc87427_probe(struct platform_device *pdev)
+static int pc87427_probe(struct platform_device *pdev)
{
struct pc87427_sio_data *sio_data = pdev->dev.platform_data;
struct pc87427_data *data;
@@ -1141,7 +1141,7 @@ exit_remove_files:
return err;
}
-static int __devexit pc87427_remove(struct platform_device *pdev)
+static int pc87427_remove(struct platform_device *pdev)
{
struct pc87427_data *data = platform_get_drvdata(pdev);
@@ -1158,7 +1158,7 @@ static struct platform_driver pc87427_driver = {
.name = DRVNAME,
},
.probe = pc87427_probe,
- .remove = __devexit_p(pc87427_remove),
+ .remove = pc87427_remove,
};
static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data)
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index bcecd025fcc4..ff2ae0252a48 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -275,7 +275,7 @@ static void s3c_hwmon_remove_attr(struct device *dev,
* s3c_hwmon_probe - device probe entry.
* @dev: The device being probed.
*/
-static int __devinit s3c_hwmon_probe(struct platform_device *dev)
+static int s3c_hwmon_probe(struct platform_device *dev)
{
struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
struct s3c_hwmon *hwmon;
@@ -364,7 +364,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
return ret;
}
-static int __devexit s3c_hwmon_remove(struct platform_device *dev)
+static int s3c_hwmon_remove(struct platform_device *dev)
{
struct s3c_hwmon *hwmon = platform_get_drvdata(dev);
int i;
@@ -386,7 +386,7 @@ static struct platform_driver s3c_hwmon_driver = {
.owner = THIS_MODULE,
},
.probe = s3c_hwmon_probe,
- .remove = __devexit_p(s3c_hwmon_remove),
+ .remove = s3c_hwmon_remove,
};
module_platform_driver(s3c_hwmon_driver);
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 49f6230bdcf1..0cc99fd83e8e 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -153,7 +153,7 @@ abort:
return ret;
}
-static int __devinit sch5627_read_limits(struct sch5627_data *data)
+static int sch5627_read_limits(struct sch5627_data *data)
{
int i, val;
@@ -465,7 +465,7 @@ static int sch5627_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit sch5627_probe(struct platform_device *pdev)
+static int sch5627_probe(struct platform_device *pdev)
{
struct sch5627_data *data;
int err, build_code, build_id, hwmon_rev, val;
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index 517118016192..547b5c952eff 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -405,7 +405,7 @@ static int sch5636_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit sch5636_probe(struct platform_device *pdev)
+static int sch5636_probe(struct platform_device *pdev)
{
struct sch5636_data *data;
int i, err, val, revision[2];
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 07a0c1a0b84d..1c85d39df171 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -884,7 +884,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
return NOTIFY_OK;
}
-static int __devinit sht15_probe(struct platform_device *pdev)
+static int sht15_probe(struct platform_device *pdev)
{
int ret;
struct sht15_data *data;
@@ -1002,7 +1002,7 @@ err_release_reg:
return ret;
}
-static int __devexit sht15_remove(struct platform_device *pdev)
+static int sht15_remove(struct platform_device *pdev)
{
struct sht15_data *data = platform_get_drvdata(pdev);
@@ -1043,7 +1043,7 @@ static struct platform_driver sht15_driver = {
.owner = THIS_MODULE,
},
.probe = sht15_probe,
- .remove = __devexit_p(sht15_remove),
+ .remove = sht15_remove,
.id_table = sht15_device_ids,
};
module_platform_driver(sht15_driver);
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 5f67546950b1..2e9f9570b6f8 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -187,7 +187,7 @@ static const struct attribute_group sht21_attr_group = {
* device's name.
* Returns 0 on success.
*/
-static int __devinit sht21_probe(struct i2c_client *client,
+static int sht21_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct sht21 *sht21;
@@ -233,7 +233,7 @@ fail_remove_sysfs:
* sht21_remove() - remove device
* @client: I2C client device
*/
-static int __devexit sht21_remove(struct i2c_client *client)
+static int sht21_remove(struct i2c_client *client)
{
struct sht21 *sht21 = i2c_get_clientdata(client);
@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(i2c, sht21_id);
static struct i2c_driver sht21_driver = {
.driver.name = "sht21",
.probe = sht21_probe,
- .remove = __devexit_p(sht21_remove),
+ .remove = sht21_remove,
.id_table = sht21_id,
};
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 8275f0e14eb7..06ce3c911db9 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -204,7 +204,7 @@ struct sis5595_data {
static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
static int sis5595_probe(struct platform_device *pdev);
-static int __devexit sis5595_remove(struct platform_device *pdev);
+static int sis5595_remove(struct platform_device *pdev);
static int sis5595_read_value(struct sis5595_data *data, u8 reg);
static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
@@ -217,7 +217,7 @@ static struct platform_driver sis5595_driver = {
.name = "sis5595",
},
.probe = sis5595_probe,
- .remove = __devexit_p(sis5595_remove),
+ .remove = sis5595_remove,
};
/* 4 Voltages */
@@ -583,7 +583,7 @@ static const struct attribute_group sis5595_group_temp1 = {
};
/* This is called when the module is loaded */
-static int __devinit sis5595_probe(struct platform_device *pdev)
+static int sis5595_probe(struct platform_device *pdev)
{
int err = 0;
int i;
@@ -659,7 +659,7 @@ exit_remove_files:
return err;
}
-static int __devexit sis5595_remove(struct platform_device *pdev)
+static int sis5595_remove(struct platform_device *pdev)
{
struct sis5595_data *data = platform_get_drvdata(pdev);
@@ -693,7 +693,7 @@ static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
}
/* Called when we have found a new SIS5595. */
-static void __devinit sis5595_init_device(struct sis5595_data *data)
+static void sis5595_init_device(struct sis5595_data *data)
{
u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
if (!(config & 0x01))
@@ -758,7 +758,7 @@ static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
-static int blacklist[] __devinitdata = {
+static int blacklist[] = {
PCI_DEVICE_ID_SI_540,
PCI_DEVICE_ID_SI_550,
PCI_DEVICE_ID_SI_630,
@@ -774,7 +774,7 @@ static int blacklist[] __devinitdata = {
PCI_DEVICE_ID_SI_5598,
0 };
-static int __devinit sis5595_device_add(unsigned short address)
+static int sis5595_device_add(unsigned short address)
{
struct resource res = {
.start = address,
@@ -815,7 +815,7 @@ exit:
return err;
}
-static int __devinit sis5595_pci_probe(struct pci_dev *dev,
+static int sis5595_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 address;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 65b07de11a0f..81348fadf3b6 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -228,7 +228,7 @@ static const struct attribute_group smsc47b397_group = {
.attrs = smsc47b397_attributes,
};
-static int __devexit smsc47b397_remove(struct platform_device *pdev)
+static int smsc47b397_remove(struct platform_device *pdev)
{
struct smsc47b397_data *data = platform_get_drvdata(pdev);
@@ -246,10 +246,10 @@ static struct platform_driver smsc47b397_driver = {
.name = DRVNAME,
},
.probe = smsc47b397_probe,
- .remove = __devexit_p(smsc47b397_remove),
+ .remove = smsc47b397_remove,
};
-static int __devinit smsc47b397_probe(struct platform_device *pdev)
+static int smsc47b397_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct smsc47b397_data *data;
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index b8777e54190a..b10c3d36ccbc 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -147,7 +147,7 @@ static const struct attribute_group tmp102_attr_group = {
#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
-static int __devinit tmp102_probe(struct i2c_client *client,
+static int tmp102_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tmp102 *tmp102;
@@ -216,7 +216,7 @@ fail_restore_config:
return status;
}
-static int __devexit tmp102_remove(struct i2c_client *client)
+static int tmp102_remove(struct i2c_client *client)
{
struct tmp102 *tmp102 = i2c_get_clientdata(client);
@@ -283,7 +283,7 @@ static struct i2c_driver tmp102_driver = {
.driver.name = DRIVER_NAME,
.driver.pm = TMP102_DEV_PM_OPS,
.probe = tmp102_probe,
- .remove = __devexit_p(tmp102_remove),
+ .remove = tmp102_remove,
.id_table = tmp102_id,
};
diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c
index 1a174f0a3cde..149d44a7c584 100644
--- a/drivers/hwmon/twl4030-madc-hwmon.c
+++ b/drivers/hwmon/twl4030-madc-hwmon.c
@@ -96,7 +96,7 @@ static const struct attribute_group twl4030_madc_group = {
.attrs = twl4030_madc_attributes,
};
-static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
+static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
{
int ret;
struct device *hwmon;
@@ -120,7 +120,7 @@ err_sysfs:
return ret;
}
-static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev)
+static int twl4030_madc_hwmon_remove(struct platform_device *pdev)
{
hwmon_device_unregister(&pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index 44136bb6d045..fb3e69341c1b 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -250,7 +250,7 @@ static const struct attribute_group env_group = {
.attrs = env_attributes,
};
-static int __devinit env_probe(struct platform_device *op)
+static int env_probe(struct platform_device *op)
{
struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
int err = -ENOMEM;
@@ -291,7 +291,7 @@ out_free:
goto out;
}
-static int __devexit env_remove(struct platform_device *op)
+static int env_remove(struct platform_device *op)
{
struct env *p = platform_get_drvdata(op);
@@ -321,7 +321,7 @@ static struct platform_driver env_driver = {
.of_match_table = env_match,
},
.probe = env_probe,
- .remove = __devexit_p(env_remove),
+ .remove = env_remove,
};
module_platform_driver(env_driver);
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 4cddee04f2e6..76f157b568ed 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -121,7 +121,7 @@ static const struct attribute_group via_cputemp_group = {
/* Optional attributes */
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL);
-static int __devinit via_cputemp_probe(struct platform_device *pdev)
+static int via_cputemp_probe(struct platform_device *pdev)
{
struct via_cputemp_data *data;
struct cpuinfo_x86 *c = &cpu_data(pdev->id);
@@ -192,7 +192,7 @@ exit_remove:
return err;
}
-static int __devexit via_cputemp_remove(struct platform_device *pdev)
+static int via_cputemp_remove(struct platform_device *pdev)
{
struct via_cputemp_data *data = platform_get_drvdata(pdev);
@@ -209,7 +209,7 @@ static struct platform_driver via_cputemp_driver = {
.name = DRVNAME,
},
.probe = via_cputemp_probe,
- .remove = __devexit_p(via_cputemp_remove),
+ .remove = via_cputemp_remove,
};
struct pdev_entry {
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 299399aa30fe..e0e14a9f1658 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -339,7 +339,7 @@ struct via686a_data {
static struct pci_dev *s_bridge; /* pointer to the (only) via686a */
static int via686a_probe(struct platform_device *pdev);
-static int __devexit via686a_remove(struct platform_device *pdev);
+static int via686a_remove(struct platform_device *pdev);
static inline int via686a_read_value(struct via686a_data *data, u8 reg)
{
@@ -677,12 +677,12 @@ static struct platform_driver via686a_driver = {
.name = "via686a",
},
.probe = via686a_probe,
- .remove = __devexit_p(via686a_remove),
+ .remove = via686a_remove,
};
/* This is called when the module is loaded */
-static int __devinit via686a_probe(struct platform_device *pdev)
+static int via686a_probe(struct platform_device *pdev)
{
struct via686a_data *data;
struct resource *res;
@@ -728,7 +728,7 @@ exit_remove_files:
return err;
}
-static int __devexit via686a_remove(struct platform_device *pdev)
+static int via686a_remove(struct platform_device *pdev)
{
struct via686a_data *data = platform_get_drvdata(pdev);
@@ -745,7 +745,7 @@ static void via686a_update_fan_div(struct via686a_data *data)
data->fan_div[1] = reg >> 6;
}
-static void __devinit via686a_init_device(struct via686a_data *data)
+static void via686a_init_device(struct via686a_data *data)
{
u8 reg;
@@ -833,7 +833,7 @@ static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
};
MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
-static int __devinit via686a_device_add(unsigned short address)
+static int via686a_device_add(unsigned short address)
{
struct resource res = {
.start = address,
@@ -874,7 +874,7 @@ exit:
return err;
}
-static int __devinit via686a_pci_probe(struct pci_dev *dev,
+static int via686a_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 address, val;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index f2c61153dba9..751703059fae 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -1086,7 +1086,7 @@ static struct device_attribute vt1211_sysfs_misc[] = {
* Device registration and initialization
* --------------------------------------------------------------------- */
-static void __devinit vt1211_init_device(struct vt1211_data *data)
+static void vt1211_init_device(struct vt1211_data *data)
{
/* set VRM */
data->vrm = vid_which_vrm();
@@ -1141,7 +1141,7 @@ static void vt1211_remove_sysfs(struct platform_device *pdev)
device_remove_file(dev, &vt1211_sysfs_misc[i]);
}
-static int __devinit vt1211_probe(struct platform_device *pdev)
+static int vt1211_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct vt1211_data *data;
@@ -1217,7 +1217,7 @@ EXIT_DEV_REMOVE_SILENT:
return err;
}
-static int __devexit vt1211_remove(struct platform_device *pdev)
+static int vt1211_remove(struct platform_device *pdev)
{
struct vt1211_data *data = platform_get_drvdata(pdev);
@@ -1233,7 +1233,7 @@ static struct platform_driver vt1211_driver = {
.name = DRVNAME,
},
.probe = vt1211_probe,
- .remove = __devexit_p(vt1211_remove),
+ .remove = vt1211_remove,
};
static int __init vt1211_device_add(unsigned short address)
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 84e3dc5e3a83..a56355cef184 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -176,7 +176,7 @@ struct vt8231_data {
static struct pci_dev *s_bridge;
static int vt8231_probe(struct platform_device *pdev);
-static int __devexit vt8231_remove(struct platform_device *pdev);
+static int vt8231_remove(struct platform_device *pdev);
static struct vt8231_data *vt8231_update_device(struct device *dev);
static void vt8231_init_device(struct vt8231_data *data);
@@ -762,7 +762,7 @@ static struct platform_driver vt8231_driver = {
.name = "vt8231",
},
.probe = vt8231_probe,
- .remove = __devexit_p(vt8231_remove),
+ .remove = vt8231_remove,
};
static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
@@ -772,7 +772,7 @@ static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+static int vt8231_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id);
static struct pci_driver vt8231_pci_driver = {
@@ -851,7 +851,7 @@ exit_remove_files:
return err;
}
-static int __devexit vt8231_remove(struct platform_device *pdev)
+static int vt8231_remove(struct platform_device *pdev)
{
struct vt8231_data *data = platform_get_drvdata(pdev);
int i;
@@ -943,7 +943,7 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
return data;
}
-static int __devinit vt8231_device_add(unsigned short address)
+static int vt8231_device_add(unsigned short address)
{
struct resource res = {
.start = address,
@@ -984,7 +984,7 @@ exit:
return err;
}
-static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+static int vt8231_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 address, val;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index de3c7e04c3b5..55ac41c05561 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1866,7 +1866,7 @@ static void w83627ehf_device_remove_files(struct device *dev)
}
/* Get the monitoring functions started */
-static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data,
+static inline void w83627ehf_init_device(struct w83627ehf_data *data,
enum kinds kind)
{
int i;
@@ -1952,7 +1952,7 @@ static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
data->reg_temp_config[r2] = tmp;
}
-static void __devinit
+static void
w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
{
int i;
@@ -1965,7 +1965,7 @@ w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp)
}
}
-static void __devinit
+static void
w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
struct w83627ehf_data *data)
{
@@ -2054,7 +2054,7 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
}
}
-static int __devinit w83627ehf_probe(struct platform_device *pdev)
+static int w83627ehf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct w83627ehf_sio_data *sio_data = dev->platform_data;
@@ -2596,7 +2596,7 @@ exit:
return err;
}
-static int __devexit w83627ehf_remove(struct platform_device *pdev)
+static int w83627ehf_remove(struct platform_device *pdev)
{
struct w83627ehf_data *data = platform_get_drvdata(pdev);
@@ -2614,7 +2614,7 @@ static struct platform_driver w83627ehf_driver = {
.name = DRVNAME,
},
.probe = w83627ehf_probe,
- .remove = __devexit_p(w83627ehf_remove),
+ .remove = w83627ehf_remove,
};
/* w83627ehf_find() looks for a '627 in the Super-I/O config space */
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index af1589908709..7f68b8309d10 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -393,7 +393,7 @@ struct w83627hf_data {
static int w83627hf_probe(struct platform_device *pdev);
-static int __devexit w83627hf_remove(struct platform_device *pdev);
+static int w83627hf_remove(struct platform_device *pdev);
static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
@@ -407,7 +407,7 @@ static struct platform_driver w83627hf_driver = {
.name = DRVNAME,
},
.probe = w83627hf_probe,
- .remove = __devexit_p(w83627hf_remove),
+ .remove = w83627hf_remove,
};
static ssize_t
@@ -1342,7 +1342,7 @@ static const struct attribute_group w83627hf_group_opt = {
.attrs = w83627hf_attributes_opt,
};
-static int __devinit w83627hf_probe(struct platform_device *pdev)
+static int w83627hf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct w83627hf_sio_data *sio_data = dev->platform_data;
@@ -1508,7 +1508,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
return err;
}
-static int __devexit w83627hf_remove(struct platform_device *pdev)
+static int w83627hf_remove(struct platform_device *pdev)
{
struct w83627hf_data *data = platform_get_drvdata(pdev);
@@ -1564,7 +1564,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
return res;
}
-static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
+static int w83627thf_read_gpio5(struct platform_device *pdev)
{
struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
int res = 0xff, sel;
@@ -1597,7 +1597,7 @@ exit:
return res;
}
-static int __devinit w83687thf_read_vid(struct platform_device *pdev)
+static int w83687thf_read_vid(struct platform_device *pdev)
{
struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
int res = 0xff;
@@ -1649,7 +1649,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value)
return 0;
}
-static void __devinit w83627hf_init_device(struct platform_device *pdev)
+static void w83627hf_init_device(struct platform_device *pdev)
{
struct w83627hf_data *data = platform_get_drvdata(pdev);
int i;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 20f11d31da40..93bd28639595 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1764,7 +1764,7 @@ w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
return 0;
}
-static int __devinit
+static int
w83781d_isa_probe(struct platform_device *pdev)
{
int err, reg;
@@ -1824,7 +1824,7 @@ w83781d_isa_probe(struct platform_device *pdev)
return err;
}
-static int __devexit
+static int
w83781d_isa_remove(struct platform_device *pdev)
{
struct w83781d_data *data = platform_get_drvdata(pdev);
@@ -1842,7 +1842,7 @@ static struct platform_driver w83781d_isa_driver = {
.name = "w83781d",
},
.probe = w83781d_isa_probe,
- .remove = __devexit_p(w83781d_isa_remove),
+ .remove = w83781d_isa_remove,
};
/* return 1 if a supported chip is found, 0 otherwise */
diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
index d0db1f2738fb..df6ceaf8d58a 100644
--- a/drivers/hwmon/wm831x-hwmon.c
+++ b/drivers/hwmon/wm831x-hwmon.c
@@ -157,7 +157,7 @@ static const struct attribute_group wm831x_attr_group = {
.attrs = wm831x_attributes,
};
-static int __devinit wm831x_hwmon_probe(struct platform_device *pdev)
+static int wm831x_hwmon_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_hwmon *hwmon;
@@ -189,7 +189,7 @@ err_sysfs:
return ret;
}
-static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
+static int wm831x_hwmon_remove(struct platform_device *pdev)
{
struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev);
@@ -201,7 +201,7 @@ static int __devexit wm831x_hwmon_remove(struct platform_device *pdev)
static struct platform_driver wm831x_hwmon_driver = {
.probe = wm831x_hwmon_probe,
- .remove = __devexit_p(wm831x_hwmon_remove),
+ .remove = wm831x_hwmon_remove,
.driver = {
.name = "wm831x-hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c
index b955756bdb42..64bf75c9442b 100644
--- a/drivers/hwmon/wm8350-hwmon.c
+++ b/drivers/hwmon/wm8350-hwmon.c
@@ -91,7 +91,7 @@ static const struct attribute_group wm8350_attr_group = {
.attrs = wm8350_attributes,
};
-static int __devinit wm8350_hwmon_probe(struct platform_device *pdev)
+static int wm8350_hwmon_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
int ret;
@@ -114,7 +114,7 @@ err:
return ret;
}
-static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
+static int wm8350_hwmon_remove(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
@@ -126,7 +126,7 @@ static int __devexit wm8350_hwmon_remove(struct platform_device *pdev)
static struct platform_driver wm8350_hwmon_driver = {
.probe = wm8350_hwmon_probe,
- .remove = __devexit_p(wm8350_hwmon_remove),
+ .remove = wm8350_hwmon_remove,
.driver = {
.name = "wm8350-hwmon",
.owner = THIS_MODULE,
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index 887d34effb3a..292869cc9034 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -78,7 +78,7 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
.relax = omap_hwspinlock_relax,
};
-static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
+static int omap_hwspinlock_probe(struct platform_device *pdev)
{
struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
struct hwspinlock_device *bank;
@@ -142,7 +142,7 @@ iounmap_base:
return ret;
}
-static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
+static int omap_hwspinlock_remove(struct platform_device *pdev)
{
struct hwspinlock_device *bank = platform_get_drvdata(pdev);
void __iomem *io_base = bank->lock[0].priv - LOCK_BASE_OFFSET;
@@ -163,7 +163,7 @@ static int __devexit omap_hwspinlock_remove(struct platform_device *pdev)
static struct platform_driver omap_hwspinlock_driver = {
.probe = omap_hwspinlock_probe,
- .remove = __devexit_p(omap_hwspinlock_remove),
+ .remove = omap_hwspinlock_remove,
.driver = {
.name = "omap_hwspinlock",
.owner = THIS_MODULE,
diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
index 86980fe04117..401c33bcdb45 100644
--- a/drivers/hwspinlock/u8500_hsem.c
+++ b/drivers/hwspinlock/u8500_hsem.c
@@ -91,7 +91,7 @@ static const struct hwspinlock_ops u8500_hwspinlock_ops = {
.relax = u8500_hsem_relax,
};
-static int __devinit u8500_hsem_probe(struct platform_device *pdev)
+static int u8500_hsem_probe(struct platform_device *pdev)
{
struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
struct hwspinlock_device *bank;
@@ -148,7 +148,7 @@ iounmap_base:
return ret;
}
-static int __devexit u8500_hsem_remove(struct platform_device *pdev)
+static int u8500_hsem_remove(struct platform_device *pdev)
{
struct hwspinlock_device *bank = platform_get_drvdata(pdev);
void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
@@ -172,7 +172,7 @@ static int __devexit u8500_hsem_remove(struct platform_device *pdev)
static struct platform_driver u8500_hsem_driver = {
.probe = u8500_hsem_probe,
- .remove = __devexit_p(u8500_hsem_remove),
+ .remove = u8500_hsem_remove,
.driver = {
.name = "u8500_hsem",
.owner = THIS_MODULE,
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index aa59a254be2c..c02bf208084f 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -39,6 +39,7 @@
#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */
#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */
#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */
+#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */
#define AT91_TWI_SWRST 0x0080 /* Software Reset */
#define AT91_TWI_MMR 0x0004 /* Master Mode Register */
@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
INIT_COMPLETION(dev->cmd_complete);
dev->transfer_status = 0;
- if (dev->msg->flags & I2C_M_RD) {
+
+ if (!dev->buf_len) {
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+ } else if (dev->msg->flags & I2C_M_RD) {
unsigned start_flags = AT91_TWI_START;
if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 286ca1917820..0670da79ee5e 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -287,12 +287,14 @@ read_init_dma_fail:
select_init_dma_fail:
dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
select_init_pio_fail:
+ dmaengine_terminate_all(i2c->dmach);
return -EINVAL;
/* Write failpath. */
write_init_dma_fail:
dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
write_init_pio_fail:
+ dmaengine_terminate_all(i2c->dmach);
return -EINVAL;
}
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index bffd5501ac2d..15da1ac7cf9e 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -9,10 +9,6 @@
* kind, whether express or implied.
*/
-/*
- * This driver can be used from the device tree, see
- * Documentation/devicetree/bindings/i2c/ocore-i2c.txt
- */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index db31eaed6ea5..3525c9e62cb0 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -43,7 +43,6 @@
#include <linux/slab.h>
#include <linux/i2c-omap.h>
#include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
/* I2C controller revisions */
#define OMAP_I2C_OMAP1_REV_2 0x20
@@ -187,8 +186,9 @@ struct omap_i2c_dev {
int reg_shift; /* bit shift for I2C register addresses */
struct completion cmd_complete;
struct resource *ioarea;
- u32 latency; /* maximum MPU wkup latency */
- struct pm_qos_request pm_qos_request;
+ u32 latency; /* maximum mpu wkup latency */
+ void (*set_mpu_wkup_lat)(struct device *dev,
+ long latency);
u32 speed; /* Speed of bus in kHz */
u32 dtrev; /* extra revision from DT */
u32 flags;
@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */
- dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+ if (dev->set_mpu_wkup_lat != NULL)
+ dev->latency = (1000000 * dev->threshold) /
+ (1000 * dev->speed / 8);
}
/*
@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
dev->buf = msg->buf;
dev->buf_len = msg->len;
+ /* make sure writes to dev->buf_len are ordered */
+ barrier();
+
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
/* Clear the FIFO Buffers */
@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
*/
timeout = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT);
- dev->buf_len = 0;
if (timeout == 0) {
dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev);
@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if (r < 0)
goto out;
- /*
- * When waiting for completion of a i2c transfer, we need to
- * set a wake up latency constraint for the MPU. This is to
- * ensure quick enough wakeup from idle, when transfer
- * completes.
- */
- if (dev->latency)
- pm_qos_add_request(&dev->pm_qos_request,
- PM_QOS_CPU_DMA_LATENCY,
- dev->latency);
+ if (dev->set_mpu_wkup_lat != NULL)
+ dev->set_mpu_wkup_lat(dev->dev, dev->latency);
for (i = 0; i < num; i++) {
r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
break;
}
- if (dev->latency)
- pm_qos_remove_request(&dev->pm_qos_request);
+ if (dev->set_mpu_wkup_lat != NULL)
+ dev->set_mpu_wkup_lat(dev->dev, -1);
if (r == 0)
r = num;
@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
} else if (pdata != NULL) {
dev->speed = pdata->clkrate;
dev->flags = pdata->flags;
+ dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
dev->dtrev = pdata->rev;
}
@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */
- dev->latency = (1000000 * dev->fifo_size) /
- (1000 * dev->speed / 8);
+ if (dev->set_mpu_wkup_lat != NULL)
+ dev->latency = (1000000 * dev->fifo_size) /
+ (1000 * dev->speed / 8);
}
/* reset ASAP, clearing any IRQs */
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 3e0335f1fc60..9d902725bac9 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
goto free_gpio;
}
+ i2c->gpios[idx] = gpio;
ret = gpio_request(gpio, "i2c-bus");
if (ret) {
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a7edf987a339..e388590b44ab 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -39,6 +39,7 @@
#include <linux/irqflags.h>
#include <linux/rwsem.h>
#include <linux/pm_runtime.h>
+#include <linux/acpi.h>
#include <asm/uaccess.h>
#include "i2c-core.h"
@@ -78,6 +79,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
if (of_driver_match_device(dev, drv))
return 1;
+ /* Then ACPI style match */
+ if (acpi_driver_match_device(dev, drv))
+ return 1;
+
driver = to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver->id_table)
@@ -539,6 +544,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
client->dev.of_node = info->of_node;
+ ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle);
/* For 10-bit clients, add an arbitrary offset to avoid collisions */
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index b0f6b4c8ee14..c49c04d9c2b0 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -56,7 +56,6 @@
#include <linux/kernel.h>
#include <linux/cpuidle.h>
#include <linux/clockchips.h>
-#include <linux/hrtimer.h> /* ktime_get_real() */
#include <trace/events/power.h>
#include <linux/sched.h>
#include <linux/notifier.h>
@@ -72,6 +71,7 @@
static struct cpuidle_driver intel_idle_driver = {
.name = "intel_idle",
.owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
};
/* intel_idle.max_cstate=0 disables driver */
static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
@@ -281,8 +281,6 @@ static int intel_idle(struct cpuidle_device *dev,
struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
unsigned int cstate;
- ktime_t kt_before, kt_after;
- s64 usec_delta;
int cpu = smp_processor_id();
cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
@@ -297,8 +295,6 @@ static int intel_idle(struct cpuidle_device *dev,
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
- kt_before = ktime_get_real();
-
stop_critical_timings();
if (!need_resched()) {
@@ -310,17 +306,9 @@ static int intel_idle(struct cpuidle_device *dev,
start_critical_timings();
- kt_after = ktime_get_real();
- usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
-
- local_irq_enable();
-
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
- /* Update cpuidle counters */
- dev->last_residency = (int)usec_delta;
-
return index;
}
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index c0ec7d42c3be..1abbc170d8b7 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
* input_mt_init_slots() - initialize MT input slots
* @dev: input device supporting MT events and finger tracking
* @num_slots: number of slots used by the device
+ * @flags: mt tasks to handle in core
*
* This function allocates all necessary memory for MT slot handling
* in the input device, prepares the ABS_MT_SLOT and
* ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * Depending on the flags set, it also performs pointer emulation and
+ * frame synchronization.
+ *
* May be called repeatedly. Returns -EINVAL if attempting to
* reinitialize with a different number of slots.
*/
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 443ad64b7f2a..d88d9be1d1b7 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -23,6 +23,7 @@
#include <linux/input.h>
#include <linux/of.h>
#include <linux/export.h>
+#include <linux/module.h>
#include <linux/input/matrix_keypad.h>
static bool matrix_keypad_map_key(struct input_dev *input_dev,
@@ -161,3 +162,5 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
return 0;
}
EXPORT_SYMBOL(matrix_keypad_build_keymap);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 8f02e3d0e712..4c842c320c2e 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -12,8 +12,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define MOUSEDEV_MINOR_BASE 32
-#define MOUSEDEV_MINORS 32
-#define MOUSEDEV_MIX 31
+#define MOUSEDEV_MINORS 31
+#define MOUSEDEV_MIX 63
#include <linux/sched.h>
#include <linux/slab.h>
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index f02028ec3db6..78e5d9ab0ba7 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
-static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+ struct ads7846 *ts)
{
struct ads7846_platform_data *pdata = spi->dev.platform_data;
int err;
@@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
ts->gpio_pendown = pdata->gpio_pendown;
+ if (pdata->gpio_pendown_debounce)
+ gpio_set_debounce(pdata->gpio_pendown,
+ pdata->gpio_pendown_debounce);
} else {
dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
return -EINVAL;
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index d4a4cd445cab..0badfa48b32b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
static int intel_iommu_add_device(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
- struct pci_dev *bridge, *dma_pdev;
+ struct pci_dev *bridge, *dma_pdev = NULL;
struct iommu_group *group;
int ret;
@@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev)
dma_pdev = pci_get_domain_bus_and_slot(
pci_domain_nr(pdev->bus),
bridge->subordinate->number, 0);
- else
+ if (!dma_pdev)
dma_pdev = pci_dev_get(bridge);
} else
dma_pdev = pci_dev_get(pdev);
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index a649f146d17b..c0f7a4266263 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
stats[i], val, offs);
}
seq_printf(s, "\n");
+ dput(dent);
return 0;
}
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index aa56a867693a..dcd9128a51a9 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -85,7 +85,7 @@ static int adp5520_led_setup(struct adp5520_led *led)
return ret;
}
-static int __devinit adp5520_led_prepare(struct platform_device *pdev)
+static int adp5520_led_prepare(struct platform_device *pdev)
{
struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
struct device *dev = pdev->dev.parent;
@@ -101,7 +101,7 @@ static int __devinit adp5520_led_prepare(struct platform_device *pdev)
return ret;
}
-static int __devinit adp5520_led_probe(struct platform_device *pdev)
+static int adp5520_led_probe(struct platform_device *pdev)
{
struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
struct adp5520_led *led, *led_dat;
@@ -183,7 +183,7 @@ err:
return ret;
}
-static int __devexit adp5520_led_remove(struct platform_device *pdev)
+static int adp5520_led_remove(struct platform_device *pdev)
{
struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
struct adp5520_led *led;
@@ -208,7 +208,7 @@ static struct platform_driver adp5520_led_driver = {
.owner = THIS_MODULE,
},
.probe = adp5520_led_probe,
- .remove = __devexit_p(adp5520_led_remove),
+ .remove = adp5520_led_remove,
};
module_platform_driver(adp5520_led_driver);
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index 5de74ff90dcf..b474745e001b 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -92,7 +92,7 @@ static int blink_set(struct led_classdev *cdev,
return 0;
}
-static int __devinit asic3_led_probe(struct platform_device *pdev)
+static int asic3_led_probe(struct platform_device *pdev)
{
struct asic3_led *led = pdev->dev.platform_data;
int ret;
@@ -125,7 +125,7 @@ out:
return ret;
}
-static int __devexit asic3_led_remove(struct platform_device *pdev)
+static int asic3_led_remove(struct platform_device *pdev)
{
struct asic3_led *led = pdev->dev.platform_data;
@@ -167,7 +167,7 @@ static const struct dev_pm_ops asic3_led_pm_ops = {
static struct platform_driver asic3_led_driver = {
.probe = asic3_led_probe,
- .remove = __devexit_p(asic3_led_remove),
+ .remove = asic3_led_remove,
.driver = {
.name = "leds-asic3",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 45430632faab..386773532d95 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -35,7 +35,7 @@ static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
* NOTE: we reuse the platform_data structure of GPIO leds,
* but repurpose its "gpio" number as a PWM channel number.
*/
-static int __devinit pwmled_probe(struct platform_device *pdev)
+static int pwmled_probe(struct platform_device *pdev)
{
const struct gpio_led_platform_data *pdata;
struct pwmled *leds;
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 89ca6a2a19d1..9abe8de40edd 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -670,7 +670,7 @@ static void bd2802_unregister_led_classdev(struct bd2802_led *led)
led_classdev_unregister(&led->cdev_led1r);
}
-static int __devinit bd2802_probe(struct i2c_client *client,
+static int bd2802_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct bd2802_led *led;
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index f7c3d7f1ec52..a502678cc7f5 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -632,7 +632,7 @@ static int blinkm_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0;
}
-static int __devinit blinkm_probe(struct i2c_client *client,
+static int blinkm_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct blinkm_data *data;
@@ -743,7 +743,7 @@ exit:
return err;
}
-static int __devexit blinkm_remove(struct i2c_client *client)
+static int blinkm_remove(struct i2c_client *client)
{
struct blinkm_data *data = i2c_get_clientdata(client);
int ret = 0;
@@ -801,7 +801,7 @@ static struct i2c_driver blinkm_driver = {
.name = "blinkm",
},
.probe = blinkm_probe,
- .remove = __devexit_p(blinkm_remove),
+ .remove = blinkm_remove,
.id_table = blinkm_id,
.detect = blinkm_detect,
.address_list = normal_i2c,
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index e024b0b1c3b1..b02547052e12 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -153,7 +153,7 @@ static struct led_classdev clevo_mail_led = {
.flags = LED_CORE_SUSPENDRESUME,
};
-static int __devinit clevo_mail_led_probe(struct platform_device *pdev)
+static int clevo_mail_led_probe(struct platform_device *pdev)
{
return led_classdev_register(&pdev->dev, &clevo_mail_led);
}
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 6a8725cc7b4d..ffa99303b629 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -34,7 +34,7 @@ static struct led_classdev qube_front_led = {
.default_trigger = "default-on",
};
-static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
+static int cobalt_qube_led_probe(struct platform_device *pdev)
{
struct resource *res;
int retval;
@@ -63,7 +63,7 @@ err_iounmap:
return retval;
}
-static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
+static int cobalt_qube_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&qube_front_led);
@@ -77,7 +77,7 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
static struct platform_driver cobalt_qube_led_driver = {
.probe = cobalt_qube_led_probe,
- .remove = __devexit_p(cobalt_qube_led_remove),
+ .remove = cobalt_qube_led_remove,
.driver = {
.name = "cobalt-qube-leds",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index aac1c073fe7b..d52e47de396f 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -76,7 +76,7 @@ static struct led_classdev raq_power_off_led = {
.default_trigger = "power-off",
};
-static int __devinit cobalt_raq_led_probe(struct platform_device *pdev)
+static int cobalt_raq_led_probe(struct platform_device *pdev)
{
struct resource *res;
int retval;
@@ -109,7 +109,7 @@ err_iounmap:
return retval;
}
-static int __devexit cobalt_raq_led_remove(struct platform_device *pdev)
+static int cobalt_raq_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&raq_power_off_led);
led_classdev_unregister(&raq_web_led);
@@ -124,7 +124,7 @@ static int __devexit cobalt_raq_led_remove(struct platform_device *pdev)
static struct platform_driver cobalt_raq_led_driver = {
.probe = cobalt_raq_led_probe,
- .remove = __devexit_p(cobalt_raq_led_remove),
+ .remove = cobalt_raq_led_remove,
.driver = {
.name = "cobalt-raq-leds",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index cc77c9d92615..6f31b776765b 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -91,7 +91,7 @@ static void da903x_led_set(struct led_classdev *led_cdev,
schedule_work(&led->work);
}
-static int __devinit da903x_led_probe(struct platform_device *pdev)
+static int da903x_led_probe(struct platform_device *pdev)
{
struct led_info *pdata = pdev->dev.platform_data;
struct da903x_led *led;
@@ -136,7 +136,7 @@ static int __devinit da903x_led_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit da903x_led_remove(struct platform_device *pdev)
+static int da903x_led_remove(struct platform_device *pdev)
{
struct da903x_led *led = platform_get_drvdata(pdev);
@@ -150,7 +150,7 @@ static struct platform_driver da903x_led_driver = {
.owner = THIS_MODULE,
},
.probe = da903x_led_probe,
- .remove = __devexit_p(da903x_led_remove),
+ .remove = da903x_led_remove,
};
module_platform_driver(da903x_led_driver);
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index 58a5244c437e..efec43344e9f 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -102,7 +102,7 @@ static int da9052_configure_leds(struct da9052 *da9052)
return error;
}
-static int __devinit da9052_led_probe(struct platform_device *pdev)
+static int da9052_led_probe(struct platform_device *pdev)
{
struct da9052_pdata *pdata;
struct da9052 *da9052;
@@ -176,7 +176,7 @@ err:
return error;
}
-static int __devexit da9052_led_remove(struct platform_device *pdev)
+static int da9052_led_remove(struct platform_device *pdev)
{
struct da9052_led *led = platform_get_drvdata(pdev);
struct da9052_pdata *pdata;
@@ -204,7 +204,7 @@ static struct platform_driver da9052_led_driver = {
.owner = THIS_MODULE,
},
.probe = da9052_led_probe,
- .remove = __devexit_p(da9052_led_remove),
+ .remove = da9052_led_remove,
};
module_platform_driver(da9052_led_driver);
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 087d1e66f4f7..291c20797ca0 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -91,7 +91,7 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
delay_on, delay_off);
}
-static int __devinit create_gpio_led(const struct gpio_led *template,
+static int create_gpio_led(const struct gpio_led *template,
struct gpio_led_data *led_dat, struct device *parent,
int (*blink_set)(unsigned, int, unsigned long *, unsigned long *))
{
@@ -167,7 +167,7 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
/* Code to create from OpenFirmware platform devices */
#ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node, *child;
struct gpio_leds_priv *priv;
@@ -224,14 +224,14 @@ static const struct of_device_id of_gpio_leds_match[] = {
{},
};
#else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
{
return NULL;
}
#endif /* CONFIG_OF_GPIO */
-static int __devinit gpio_led_probe(struct platform_device *pdev)
+static int gpio_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct gpio_leds_priv *priv;
@@ -273,7 +273,7 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit gpio_led_remove(struct platform_device *pdev)
+static int gpio_led_remove(struct platform_device *pdev)
{
struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
int i;
@@ -288,7 +288,7 @@ static int __devexit gpio_led_remove(struct platform_device *pdev)
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
- .remove = __devexit_p(gpio_led_remove),
+ .remove = gpio_led_remove,
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index b26306f6724d..214145483836 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -377,7 +377,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
-static int __devinit lm3530_probe(struct i2c_client *client,
+static int lm3530_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm3530_platform_data *pdata = client->dev.platform_data;
@@ -452,7 +452,7 @@ err_create_file:
return err;
}
-static int __devexit lm3530_remove(struct i2c_client *client)
+static int lm3530_remove(struct i2c_client *client)
{
struct lm3530_data *drvdata = i2c_get_clientdata(client);
@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(i2c, lm3530_id);
static struct i2c_driver lm3530_i2c_driver = {
.probe = lm3530_probe,
- .remove = __devexit_p(lm3530_remove),
+ .remove = lm3530_remove,
.id_table = lm3530_id,
.driver = {
.name = LM3530_NAME,
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index f6837b99908c..bbf24d038a7f 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -646,7 +646,7 @@ static struct attribute_group lm3533_led_attribute_group = {
.attrs = lm3533_led_attributes
};
-static int __devinit lm3533_led_setup(struct lm3533_led *led,
+static int lm3533_led_setup(struct lm3533_led *led,
struct lm3533_led_platform_data *pdata)
{
int ret;
@@ -658,7 +658,7 @@ static int __devinit lm3533_led_setup(struct lm3533_led *led,
return lm3533_ctrlbank_set_pwm(&led->cb, pdata->pwm);
}
-static int __devinit lm3533_led_probe(struct platform_device *pdev)
+static int lm3533_led_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_led_platform_data *pdata;
@@ -742,7 +742,7 @@ err_unregister:
return ret;
}
-static int __devexit lm3533_led_remove(struct platform_device *pdev)
+static int lm3533_led_remove(struct platform_device *pdev)
{
struct lm3533_led *led = platform_get_drvdata(pdev);
@@ -774,7 +774,7 @@ static struct platform_driver lm3533_led_driver = {
.owner = THIS_MODULE,
},
.probe = lm3533_led_probe,
- .remove = __devexit_p(lm3533_led_remove),
+ .remove = lm3533_led_remove,
.shutdown = lm3533_led_shutdown,
};
module_platform_driver(lm3533_led_driver);
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 065ec015d67a..b13ce0371918 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -168,7 +168,7 @@ static char lm355x_name[][I2C_NAME_SIZE] = {
};
/* chip initialize */
-static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
+static int lm355x_chip_init(struct lm355x_chip_data *chip)
{
int ret;
unsigned int reg_val;
@@ -420,7 +420,7 @@ static const struct regmap_config lm355x_regmap = {
};
/* module initialize */
-static int __devinit lm355x_probe(struct i2c_client *client,
+static int lm355x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm355x_platform_data *pdata = client->dev.platform_data;
@@ -526,7 +526,7 @@ err_out:
return err;
}
-static int __devexit lm355x_remove(struct i2c_client *client)
+static int lm355x_remove(struct i2c_client *client)
{
struct lm355x_chip_data *chip = i2c_get_clientdata(client);
struct lm355x_reg_data *preg = chip->regs;
@@ -560,7 +560,7 @@ static struct i2c_driver lm355x_i2c_driver = {
.pm = NULL,
},
.probe = lm355x_probe,
- .remove = __devexit_p(lm355x_remove),
+ .remove = lm355x_remove,
.id_table = lm355x_id,
};
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index 3285006e9888..215a7c1e56cc 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -93,7 +93,7 @@ struct lm3642_chip_data {
};
/* chip initialize */
-static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
+static int lm3642_chip_init(struct lm3642_chip_data *chip)
{
int ret;
struct lm3642_platform_data *pdata = chip->pdata;
@@ -313,7 +313,7 @@ static const struct regmap_config lm3642_regmap = {
.max_register = REG_MAX,
};
-static int __devinit lm3642_probe(struct i2c_client *client,
+static int lm3642_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm3642_platform_data *pdata = client->dev.platform_data;
@@ -420,7 +420,7 @@ err_out:
return err;
}
-static int __devexit lm3642_remove(struct i2c_client *client)
+static int lm3642_remove(struct i2c_client *client)
{
struct lm3642_chip_data *chip = i2c_get_clientdata(client);
@@ -450,7 +450,7 @@ static struct i2c_driver lm3642_i2c_driver = {
.pm = NULL,
},
.probe = lm3642_probe,
- .remove = __devexit_p(lm3642_remove),
+ .remove = lm3642_remove,
.id_table = lm3642_id,
};
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index c298f7d9f535..b081f67e1dea 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -374,7 +374,7 @@ exit:
return err;
}
-static int __devinit lp3944_probe(struct i2c_client *client,
+static int lp3944_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
@@ -411,7 +411,7 @@ static int __devinit lp3944_probe(struct i2c_client *client,
return 0;
}
-static int __devexit lp3944_remove(struct i2c_client *client)
+static int lp3944_remove(struct i2c_client *client)
{
struct lp3944_platform_data *pdata = client->dev.platform_data;
struct lp3944_data *data = i2c_get_clientdata(client);
@@ -446,7 +446,7 @@ static struct i2c_driver lp3944_driver = {
.name = "lp3944",
},
.probe = lp3944_probe,
- .remove = __devexit_p(lp3944_remove),
+ .remove = lp3944_remove,
.id_table = lp3944_id,
};
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 2064aefedc07..966f158a07db 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -687,7 +687,7 @@ static void lp5521_unregister_sysfs(struct i2c_client *client)
&lp5521_led_attribute_group);
}
-static int __devinit lp5521_init_led(struct lp5521_led *led,
+static int lp5521_init_led(struct lp5521_led *led,
struct i2c_client *client,
int chan, struct lp5521_platform_data *pdata)
{
@@ -736,7 +736,7 @@ static int __devinit lp5521_init_led(struct lp5521_led *led,
return 0;
}
-static int __devinit lp5521_probe(struct i2c_client *client,
+static int lp5521_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lp5521_chip *chip;
@@ -855,7 +855,7 @@ fail1:
return ret;
}
-static int __devexit lp5521_remove(struct i2c_client *client)
+static int lp5521_remove(struct i2c_client *client)
{
struct lp5521_chip *chip = i2c_get_clientdata(client);
int i;
@@ -886,7 +886,7 @@ static struct i2c_driver lp5521_driver = {
.name = "lp5521",
},
.probe = lp5521_probe,
- .remove = __devexit_p(lp5521_remove),
+ .remove = lp5521_remove,
.id_table = lp5521_id,
};
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 97994ffdc014..7e304b7ff779 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -833,7 +833,7 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
return 0;
}
-static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
+static int lp5523_init_led(struct lp5523_led *led, struct device *dev,
int chan, struct lp5523_platform_data *pdata,
const char *chip_name)
{
@@ -882,7 +882,7 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
return 0;
}
-static int __devinit lp5523_probe(struct i2c_client *client,
+static int lp5523_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lp5523_chip *chip;
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
index 64009a176651..4353942c5fd1 100644
--- a/drivers/leds/leds-lp8788.c
+++ b/drivers/leds/leds-lp8788.c
@@ -125,7 +125,7 @@ static void lp8788_brightness_set(struct led_classdev *led_cdev,
schedule_work(&led->work);
}
-static __devinit int lp8788_led_probe(struct platform_device *pdev)
+static int lp8788_led_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
struct lp8788_led_platform_data *led_pdata;
@@ -167,7 +167,7 @@ static __devinit int lp8788_led_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lp8788_led_remove(struct platform_device *pdev)
+static int lp8788_led_remove(struct platform_device *pdev)
{
struct lp8788_led *led = platform_get_drvdata(pdev);
@@ -179,7 +179,7 @@ static int __devexit lp8788_led_remove(struct platform_device *pdev)
static struct platform_driver lp8788_led_driver = {
.probe = lp8788_led_probe,
- .remove = __devexit_p(lp8788_led_remove),
+ .remove = lp8788_led_remove,
.driver = {
.name = LP8788_DEV_KEYLED,
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 09a732217f6d..34b3ba4376fc 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -82,7 +82,7 @@ static void lt3593_led_set(struct led_classdev *led_cdev,
schedule_work(&led_dat->work);
}
-static int __devinit create_lt3593_led(const struct gpio_led *template,
+static int create_lt3593_led(const struct gpio_led *template,
struct lt3593_led_data *led_dat, struct device *parent)
{
int ret, state;
@@ -140,7 +140,7 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
gpio_free(led->gpio);
}
-static int __devinit lt3593_led_probe(struct platform_device *pdev)
+static int lt3593_led_probe(struct platform_device *pdev)
{
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
struct lt3593_led_data *leds_data;
@@ -173,7 +173,7 @@ err:
return ret;
}
-static int __devexit lt3593_led_remove(struct platform_device *pdev)
+static int lt3593_led_remove(struct platform_device *pdev)
{
int i;
struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
@@ -189,7 +189,7 @@ static int __devexit lt3593_led_remove(struct platform_device *pdev)
static struct platform_driver lt3593_led_driver = {
.probe = lt3593_led_probe,
- .remove = __devexit_p(lt3593_led_remove),
+ .remove = lt3593_led_remove,
.driver = {
.name = "leds-lt3593",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index 569e36de37df..f449a8bdddc7 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -229,7 +229,7 @@ static ssize_t max8997_led_store_mode(struct device *dev,
static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
-static int __devinit max8997_led_probe(struct platform_device *pdev)
+static int max8997_led_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);
@@ -292,7 +292,7 @@ static int __devinit max8997_led_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit max8997_led_remove(struct platform_device *pdev)
+static int max8997_led_remove(struct platform_device *pdev)
{
struct max8997_led *led = platform_get_drvdata(pdev);
@@ -308,7 +308,7 @@ static struct platform_driver max8997_led_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_led_probe,
- .remove = __devexit_p(max8997_led_remove),
+ .remove = max8997_led_remove,
};
module_platform_driver(max8997_led_driver);
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index 2a5d43400677..e942adaa7504 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -128,7 +128,7 @@ static void mc13783_led_set(struct led_classdev *led_cdev,
schedule_work(&led->work);
}
-static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
+static int mc13783_led_setup(struct mc13783_led *led, int max_current)
{
int shift = 0;
int mask = 0;
@@ -181,7 +181,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
return ret;
}
-static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
+static int mc13783_leds_prepare(struct platform_device *pdev)
{
struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
@@ -262,7 +262,7 @@ out:
return ret;
}
-static int __devinit mc13783_led_probe(struct platform_device *pdev)
+static int mc13783_led_probe(struct platform_device *pdev)
{
struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13xxx_led_platform_data *led_cur;
@@ -348,7 +348,7 @@ err_register:
return ret;
}
-static int __devexit mc13783_led_remove(struct platform_device *pdev)
+static int mc13783_led_remove(struct platform_device *pdev)
{
struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct mc13783_led *led = platform_get_drvdata(pdev);
@@ -381,7 +381,7 @@ static struct platform_driver mc13783_led_driver = {
.owner = THIS_MODULE,
},
.probe = mc13783_led_probe,
- .remove = __devexit_p(mc13783_led_remove),
+ .remove = mc13783_led_remove,
};
module_platform_driver(mc13783_led_driver);
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index 461bbf9b33fa..58a800b17dc7 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -71,7 +71,7 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
spin_unlock_irqrestore(&gpio_ext_lock, flags);
}
-static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
+static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
{
int err;
int i;
@@ -301,7 +301,7 @@ static void delete_netxbig_led(struct netxbig_led_data *led_dat)
led_classdev_unregister(&led_dat->cdev);
}
-static int __devinit
+static int
create_netxbig_led(struct platform_device *pdev,
struct netxbig_led_data *led_dat,
const struct netxbig_led *template)
@@ -352,7 +352,7 @@ create_netxbig_led(struct platform_device *pdev,
return ret;
}
-static int __devinit netxbig_led_probe(struct platform_device *pdev)
+static int netxbig_led_probe(struct platform_device *pdev)
{
struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
struct netxbig_led_data *leds_data;
@@ -389,7 +389,7 @@ err_free_leds:
return ret;
}
-static int __devexit netxbig_led_remove(struct platform_device *pdev)
+static int netxbig_led_remove(struct platform_device *pdev)
{
struct netxbig_led_platform_data *pdata = pdev->dev.platform_data;
struct netxbig_led_data *leds_data;
@@ -407,7 +407,7 @@ static int __devexit netxbig_led_remove(struct platform_device *pdev)
static struct platform_driver netxbig_led_driver = {
.probe = netxbig_led_probe,
- .remove = __devexit_p(netxbig_led_remove),
+ .remove = netxbig_led_remove,
.driver = {
.name = "leds-netxbig",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index d176ec83f5d9..6315e88d04fd 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -184,7 +184,7 @@ static ssize_t ns2_led_sata_show(struct device *dev,
static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
-static int __devinit
+static int
create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
const struct ns2_led *template)
{
@@ -263,7 +263,7 @@ static void delete_ns2_led(struct ns2_led_data *led_dat)
gpio_free(led_dat->slow);
}
-static int __devinit ns2_led_probe(struct platform_device *pdev)
+static int ns2_led_probe(struct platform_device *pdev)
{
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
struct ns2_led_data *leds_data;
@@ -292,7 +292,7 @@ static int __devinit ns2_led_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ns2_led_remove(struct platform_device *pdev)
+static int ns2_led_remove(struct platform_device *pdev)
{
int i;
struct ns2_led_platform_data *pdata = pdev->dev.platform_data;
@@ -310,7 +310,7 @@ static int __devexit ns2_led_remove(struct platform_device *pdev)
static struct platform_driver ns2_led_driver = {
.probe = ns2_led_probe,
- .remove = __devexit_p(ns2_led_remove),
+ .remove = ns2_led_remove,
.driver = {
.name = "leds-ns2",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
index c4646825a620..ee14662ed5ce 100644
--- a/drivers/leds/leds-ot200.c
+++ b/drivers/leds/leds-ot200.c
@@ -115,7 +115,7 @@ static void ot200_led_brightness_set(struct led_classdev *led_cdev,
spin_unlock_irqrestore(&value_lock, flags);
}
-static int __devinit ot200_led_probe(struct platform_device *pdev)
+static int ot200_led_probe(struct platform_device *pdev)
{
int i;
int ret;
@@ -144,7 +144,7 @@ err:
return ret;
}
-static int __devexit ot200_led_remove(struct platform_device *pdev)
+static int ot200_led_remove(struct platform_device *pdev)
{
int i;
@@ -156,7 +156,7 @@ static int __devexit ot200_led_remove(struct platform_device *pdev)
static struct platform_driver ot200_led_driver = {
.probe = ot200_led_probe,
- .remove = __devexit_p(ot200_led_remove),
+ .remove = ot200_led_remove,
.driver = {
.name = "leds-ot200",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index aef3cf0432fe..706791af8fc8 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -255,7 +255,7 @@ static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness v
schedule_work(&pca955x->work);
}
-static int __devinit pca955x_probe(struct i2c_client *client,
+static int pca955x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca955x *pca955x;
@@ -363,7 +363,7 @@ exit:
return err;
}
-static int __devexit pca955x_remove(struct i2c_client *client)
+static int pca955x_remove(struct i2c_client *client)
{
struct pca955x *pca955x = i2c_get_clientdata(client);
int i;
@@ -382,7 +382,7 @@ static struct i2c_driver pca955x_driver = {
.owner = THIS_MODULE,
},
.probe = pca955x_probe,
- .remove = __devexit_p(pca955x_remove),
+ .remove = pca955x_remove,
.id_table = pca955x_id,
};
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index 2f2f9c43535d..9aae5679ffb2 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -93,7 +93,7 @@ static void pca9633_led_set(struct led_classdev *led_cdev,
schedule_work(&pca9633->work);
}
-static int __devinit pca9633_probe(struct i2c_client *client,
+static int pca9633_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pca9633_led *pca9633;
@@ -164,7 +164,7 @@ exit:
return err;
}
-static int __devexit pca9633_remove(struct i2c_client *client)
+static int pca9633_remove(struct i2c_client *client)
{
struct pca9633_led *pca9633 = i2c_get_clientdata(client);
int i;
@@ -183,7 +183,7 @@ static struct i2c_driver pca9633_driver = {
.owner = THIS_MODULE,
},
.probe = pca9633_probe,
- .remove = __devexit_p(pca9633_remove),
+ .remove = pca9633_remove,
.id_table = pca9633_id,
};
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index f2e44c719437..e51ff7a3cd88 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -107,7 +107,7 @@ err:
return ret;
}
-static int __devexit led_pwm_remove(struct platform_device *pdev)
+static int led_pwm_remove(struct platform_device *pdev)
{
int i;
struct led_pwm_platform_data *pdata = pdev->dev.platform_data;
@@ -125,7 +125,7 @@ static int __devexit led_pwm_remove(struct platform_device *pdev)
static struct platform_driver led_pwm_driver = {
.probe = led_pwm_probe,
- .remove = __devexit_p(led_pwm_remove),
+ .remove = led_pwm_remove,
.driver = {
.name = "leds_pwm",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
index a7815b6cd856..9ebdd5011a7c 100644
--- a/drivers/leds/leds-rb532.c
+++ b/drivers/leds/leds-rb532.c
@@ -37,12 +37,12 @@ static struct led_classdev rb532_uled = {
.default_trigger = "nand-disk",
};
-static int __devinit rb532_led_probe(struct platform_device *pdev)
+static int rb532_led_probe(struct platform_device *pdev)
{
return led_classdev_register(&pdev->dev, &rb532_uled);
}
-static int __devexit rb532_led_remove(struct platform_device *pdev)
+static int rb532_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&rb532_uled);
return 0;
@@ -50,7 +50,7 @@ static int __devexit rb532_led_remove(struct platform_device *pdev)
static struct platform_driver rb532_led_driver = {
.probe = rb532_led_probe,
- .remove = __devexit_p(rb532_led_remove),
+ .remove = rb532_led_remove,
.driver = {
.name = "rb532-led",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 25d382d60fa9..4253a9b03dbf 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -140,7 +140,7 @@ static void regulator_led_brightness_set(struct led_classdev *led_cdev,
schedule_work(&led->work);
}
-static int __devinit regulator_led_probe(struct platform_device *pdev)
+static int regulator_led_probe(struct platform_device *pdev)
{
struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
struct regulator_led *led;
@@ -206,7 +206,7 @@ err_vcc:
return ret;
}
-static int __devexit regulator_led_remove(struct platform_device *pdev)
+static int regulator_led_remove(struct platform_device *pdev)
{
struct regulator_led *led = platform_get_drvdata(pdev);
@@ -223,7 +223,7 @@ static struct platform_driver regulator_led_driver = {
.owner = THIS_MODULE,
},
.probe = regulator_led_probe,
- .remove = __devexit_p(regulator_led_remove),
+ .remove = regulator_led_remove,
};
module_platform_driver(regulator_led_driver);
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index 771ea067e680..bc8984795a3e 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -238,7 +238,7 @@ static void r_tpu_set_brightness(struct led_classdev *ldev,
schedule_work(&p->work);
}
-static int __devinit r_tpu_probe(struct platform_device *pdev)
+static int r_tpu_probe(struct platform_device *pdev)
{
struct led_renesas_tpu_config *cfg = pdev->dev.platform_data;
struct r_tpu_priv *p;
@@ -309,7 +309,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit r_tpu_remove(struct platform_device *pdev)
+static int r_tpu_remove(struct platform_device *pdev)
{
struct r_tpu_priv *p = platform_get_drvdata(pdev);
@@ -328,7 +328,7 @@ static int __devexit r_tpu_remove(struct platform_device *pdev)
static struct platform_driver r_tpu_device_driver = {
.probe = r_tpu_probe,
- .remove = __devexit_p(r_tpu_remove),
+ .remove = r_tpu_remove,
.driver = {
.name = "leds-renesas-tpu",
}
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 57371e1485ab..6469849e8266 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -263,7 +263,7 @@ static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
* already taken care of this, but we will do so in a non destructive manner
* so that we have what we need whether the BIOS did it or not.
*/
-static int __devinit ich7_gpio_init(struct device *dev)
+static int ich7_gpio_init(struct device *dev)
{
int i;
u32 config_data = 0;
@@ -342,7 +342,7 @@ static void ich7_lpc_cleanup(struct device *dev)
* so we can retrive the required operational information and prepare the GPIO.
*/
static struct pci_dev *nas_gpio_pci_dev;
-static int __devinit ich7_lpc_probe(struct pci_dev *dev,
+static int ich7_lpc_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int status;
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index 134d9a4b34f1..07ff5a3a6cee 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -123,7 +123,7 @@ struct sunfire_drvdata {
struct sunfire_led leds[NUM_LEDS_PER_BOARD];
};
-static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
+static int sunfire_led_generic_probe(struct platform_device *pdev,
struct led_type *types)
{
struct sunfire_drvdata *p;
@@ -165,7 +165,7 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev,
return 0;
}
-static int __devexit sunfire_led_generic_remove(struct platform_device *pdev)
+static int sunfire_led_generic_remove(struct platform_device *pdev)
{
struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev);
int i;
@@ -192,7 +192,7 @@ static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
},
};
-static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev)
+static int sunfire_clockboard_led_probe(struct platform_device *pdev)
{
return sunfire_led_generic_probe(pdev, clockboard_led_types);
}
@@ -213,7 +213,7 @@ static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = {
},
};
-static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev)
+static int sunfire_fhc_led_probe(struct platform_device *pdev)
{
return sunfire_led_generic_probe(pdev, fhc_led_types);
}
@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:sunfire-fhc-leds");
static struct platform_driver sunfire_clockboard_led_driver = {
.probe = sunfire_clockboard_led_probe,
- .remove = __devexit_p(sunfire_led_generic_remove),
+ .remove = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-clockboard-leds",
.owner = THIS_MODULE,
@@ -232,7 +232,7 @@ static struct platform_driver sunfire_clockboard_led_driver = {
static struct platform_driver sunfire_fhc_led_driver = {
.probe = sunfire_fhc_led_probe,
- .remove = __devexit_p(sunfire_led_generic_remove),
+ .remove = sunfire_led_generic_remove,
.driver = {
.name = "sunfire-fhc-leds",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index dabcf7ae8d0f..b26a63bae16b 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -667,7 +667,7 @@ static void tca6507_remove_gpio(struct tca6507_chip *tca)
}
#endif /* CONFIG_GPIOLIB */
-static int __devinit tca6507_probe(struct i2c_client *client,
+static int tca6507_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tca6507_chip *tca;
@@ -730,7 +730,7 @@ exit:
return err;
}
-static int __devexit tca6507_remove(struct i2c_client *client)
+static int tca6507_remove(struct i2c_client *client)
{
int i;
struct tca6507_chip *tca = i2c_get_clientdata(client);
@@ -752,7 +752,7 @@ static struct i2c_driver tca6507_driver = {
.owner = THIS_MODULE,
},
.probe = tca6507_probe,
- .remove = __devexit_p(tca6507_remove),
+ .remove = tca6507_remove,
.id_table = tca6507_id,
};
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 02db9183ca01..77e6eff41cae 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue)
if (!md_in_flight(md))
wake_up(&md->wait);
+ /*
+ * Run this off this callpath, as drivers could invoke end_io while
+ * inside their request_fn (and holding the queue lock). Calling
+ * back into ->request_fn() could deadlock attempting to grab the
+ * queue lock again.
+ */
if (run_queue)
- blk_run_queue(md->queue);
+ blk_run_queue_async(md->queue);
/*
* dm_put() must be at the end of this function. See the comment above
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9ab768acfb62..61200717687b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1817,10 +1817,10 @@ retry:
memset(bbp, 0xff, PAGE_SIZE);
for (i = 0 ; i < bb->count ; i++) {
- u64 internal_bb = *p++;
+ u64 internal_bb = p[i];
u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
| BB_LEN(internal_bb));
- *bbp++ = cpu_to_le64(store_bb);
+ bbp[i] = cpu_to_le64(store_bb);
}
bb->changed = 0;
if (read_seqretry(&bb->lock, seq))
@@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev)
}
EXPORT_SYMBOL_GPL(md_stop_writes);
-void md_stop(struct mddev *mddev)
+static void __md_stop(struct mddev *mddev)
{
mddev->ready = 0;
mddev->pers->stop(mddev);
@@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev)
mddev->pers = NULL;
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
}
+
+void md_stop(struct mddev *mddev)
+{
+ /* stop the array and free an attached data structures.
+ * This is called from dm-raid
+ */
+ __md_stop(mddev);
+ bitmap_destroy(mddev);
+ if (mddev->bio_set)
+ bioset_free(mddev->bio_set);
+}
+
EXPORT_SYMBOL_GPL(md_stop);
static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
@@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode,
set_disk_ro(disk, 0);
__md_stop_writes(mddev);
- md_stop(mddev);
+ __md_stop(mddev);
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->backing_dev_info.congested_fn = NULL;
@@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
sector_t *first_bad, int *bad_sectors)
{
int hi;
- int lo = 0;
+ int lo;
u64 *p = bb->page;
- int rv = 0;
+ int rv;
sector_t target = s + sectors;
unsigned seq;
@@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
retry:
seq = read_seqbegin(&bb->lock);
-
+ lo = 0;
+ rv = 0;
hi = bb->count;
/* Binary search between lo and hi for 'target'
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 636bae0405e8..a0f73092176e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -963,7 +963,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
struct r1conf *conf = mddev->private;
struct bio *bio;
- if (from_schedule) {
+ if (from_schedule || current->bio_list) {
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->pending_bio_list, &plug->pending);
conf->pending_count += plug->pending_cnt;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index d1295aff4173..c9acbd717131 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
*/
one_write_done(r10_bio);
if (dec_rdev)
- rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+ rdev_dec_pending(rdev, conf->mddev);
}
/*
@@ -1069,7 +1069,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
struct r10conf *conf = mddev->private;
struct bio *bio;
- if (from_schedule) {
+ if (from_schedule || current->bio_list) {
spin_lock_irq(&conf->device_lock);
bio_list_merge(&conf->pending_bio_list, &plug->pending);
conf->pending_count += plug->pending_cnt;
@@ -1334,18 +1334,21 @@ retry_write:
blocked_rdev = rrdev;
break;
}
+ if (rdev && (test_bit(Faulty, &rdev->flags)
+ || test_bit(Unmerged, &rdev->flags)))
+ rdev = NULL;
if (rrdev && (test_bit(Faulty, &rrdev->flags)
|| test_bit(Unmerged, &rrdev->flags)))
rrdev = NULL;
r10_bio->devs[i].bio = NULL;
r10_bio->devs[i].repl_bio = NULL;
- if (!rdev || test_bit(Faulty, &rdev->flags) ||
- test_bit(Unmerged, &rdev->flags)) {
+
+ if (!rdev && !rrdev) {
set_bit(R10BIO_Degraded, &r10_bio->state);
continue;
}
- if (test_bit(WriteErrorSeen, &rdev->flags)) {
+ if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
sector_t first_bad;
sector_t dev_sector = r10_bio->devs[i].addr;
int bad_sectors;
@@ -1387,8 +1390,10 @@ retry_write:
max_sectors = good_sectors;
}
}
- r10_bio->devs[i].bio = bio;
- atomic_inc(&rdev->nr_pending);
+ if (rdev) {
+ r10_bio->devs[i].bio = bio;
+ atomic_inc(&rdev->nr_pending);
+ }
if (rrdev) {
r10_bio->devs[i].repl_bio = bio;
atomic_inc(&rrdev->nr_pending);
@@ -1444,69 +1449,71 @@ retry_write:
for (i = 0; i < conf->copies; i++) {
struct bio *mbio;
int d = r10_bio->devs[i].devnum;
- if (!r10_bio->devs[i].bio)
- continue;
+ if (r10_bio->devs[i].bio) {
+ struct md_rdev *rdev = conf->mirrors[d].rdev;
+ mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+ md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+ max_sectors);
+ r10_bio->devs[i].bio = mbio;
+
+ mbio->bi_sector = (r10_bio->devs[i].addr+
+ choose_data_offset(r10_bio,
+ rdev));
+ mbio->bi_bdev = rdev->bdev;
+ mbio->bi_end_io = raid10_end_write_request;
+ mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+ mbio->bi_private = r10_bio;
- mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
- md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
- max_sectors);
- r10_bio->devs[i].bio = mbio;
+ atomic_inc(&r10_bio->remaining);
- mbio->bi_sector = (r10_bio->devs[i].addr+
- 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 | do_discard;
- mbio->bi_private = r10_bio;
+ cb = blk_check_plugged(raid10_unplug, mddev,
+ sizeof(*plug));
+ if (cb)
+ plug = container_of(cb, struct raid10_plug_cb,
+ cb);
+ else
+ plug = NULL;
+ spin_lock_irqsave(&conf->device_lock, flags);
+ if (plug) {
+ bio_list_add(&plug->pending, mbio);
+ plug->pending_cnt++;
+ } else {
+ bio_list_add(&conf->pending_bio_list, mbio);
+ conf->pending_count++;
+ }
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ if (!plug)
+ md_wakeup_thread(mddev->thread);
+ }
- atomic_inc(&r10_bio->remaining);
+ if (r10_bio->devs[i].repl_bio) {
+ struct md_rdev *rdev = conf->mirrors[d].replacement;
+ if (rdev == NULL) {
+ /* Replacement just got moved to main 'rdev' */
+ smp_mb();
+ rdev = conf->mirrors[d].rdev;
+ }
+ mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+ md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+ max_sectors);
+ r10_bio->devs[i].repl_bio = mbio;
+
+ mbio->bi_sector = (r10_bio->devs[i].addr +
+ choose_data_offset(
+ r10_bio, rdev));
+ mbio->bi_bdev = rdev->bdev;
+ mbio->bi_end_io = raid10_end_write_request;
+ mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+ mbio->bi_private = r10_bio;
- cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
- if (cb)
- plug = container_of(cb, struct raid10_plug_cb, cb);
- else
- plug = NULL;
- spin_lock_irqsave(&conf->device_lock, flags);
- if (plug) {
- bio_list_add(&plug->pending, mbio);
- plug->pending_cnt++;
- } else {
+ atomic_inc(&r10_bio->remaining);
+ spin_lock_irqsave(&conf->device_lock, flags);
bio_list_add(&conf->pending_bio_list, mbio);
conf->pending_count++;
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ if (!mddev_check_plugged(mddev))
+ md_wakeup_thread(mddev->thread);
}
- spin_unlock_irqrestore(&conf->device_lock, flags);
- if (!plug)
- md_wakeup_thread(mddev->thread);
-
- if (!r10_bio->devs[i].repl_bio)
- continue;
-
- mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
- md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
- max_sectors);
- r10_bio->devs[i].repl_bio = mbio;
-
- /* We are actively writing to the original device
- * so it cannot disappear, so the replacement cannot
- * become NULL here
- */
- 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 | do_discard;
- mbio->bi_private = r10_bio;
-
- atomic_inc(&r10_bio->remaining);
- spin_lock_irqsave(&conf->device_lock, flags);
- bio_list_add(&conf->pending_bio_list, mbio);
- conf->pending_count++;
- spin_unlock_irqrestore(&conf->device_lock, flags);
- if (!mddev_check_plugged(mddev))
- md_wakeup_thread(mddev->thread);
}
/* Don't remove the bias on 'remaining' (one_write_done) until
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index c5439dce0295..a4502686e7a8 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf,
dev = &sh->dev[i];
if (!test_bit(R5_LOCKED, &dev->flags) &&
(test_bit(R5_UPTODATE, &dev->flags) ||
- test_and_clear_bit(R5_Discard, &dev->flags))) {
+ test_bit(R5_Discard, &dev->flags))) {
/* We can return any write requests */
struct bio *wbi, *wbi2;
pr_debug("Return write for disc %d\n", i);
+ if (test_and_clear_bit(R5_Discard, &dev->flags))
+ clear_bit(R5_UPTODATE, &dev->flags);
wbi = dev->written;
dev->written = NULL;
while (wbi && wbi->bi_sector <
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
!test_bit(STRIPE_DEGRADED, &sh->state),
0);
}
- }
+ } else if (test_bit(R5_Discard, &sh->dev[i].flags))
+ clear_bit(R5_Discard, &sh->dev[i].flags);
if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh)
handle_failed_sync(conf, sh, &s);
}
- /*
- * might be able to return some write requests if the parity blocks
- * are safe, or on a failed drive
- */
- pdev = &sh->dev[sh->pd_idx];
- s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
- || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
- qdev = &sh->dev[sh->qd_idx];
- s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
- || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
- || conf->level < 6;
-
- if (s.written &&
- (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
- && !test_bit(R5_LOCKED, &pdev->flags)
- && (test_bit(R5_UPTODATE, &pdev->flags) ||
- test_bit(R5_Discard, &pdev->flags))))) &&
- (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
- && !test_bit(R5_LOCKED, &qdev->flags)
- && (test_bit(R5_UPTODATE, &qdev->flags) ||
- test_bit(R5_Discard, &qdev->flags))))))
- handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
-
- /* Now we might consider reading some blocks, either to check/generate
- * parity, or to satisfy requests
- * or to load a block that is being partially written.
- */
- if (s.to_read || s.non_overwrite
- || (conf->level == 6 && s.to_write && s.failed)
- || (s.syncing && (s.uptodate + s.compute < disks))
- || s.replacing
- || s.expanding)
- handle_stripe_fill(sh, &s, disks);
-
/* Now we check to see if any write operations have recently
* completed
*/
@@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh)
s.dec_preread_active = 1;
}
+ /*
+ * might be able to return some write requests if the parity blocks
+ * are safe, or on a failed drive
+ */
+ pdev = &sh->dev[sh->pd_idx];
+ s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+ || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+ qdev = &sh->dev[sh->qd_idx];
+ s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+ || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+ || conf->level < 6;
+
+ if (s.written &&
+ (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+ && !test_bit(R5_LOCKED, &pdev->flags)
+ && (test_bit(R5_UPTODATE, &pdev->flags) ||
+ test_bit(R5_Discard, &pdev->flags))))) &&
+ (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+ && !test_bit(R5_LOCKED, &qdev->flags)
+ && (test_bit(R5_UPTODATE, &qdev->flags) ||
+ test_bit(R5_Discard, &qdev->flags))))))
+ handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
+
+ /* Now we might consider reading some blocks, either to check/generate
+ * parity, or to satisfy requests
+ * or to load a block that is being partially written.
+ */
+ if (s.to_read || s.non_overwrite
+ || (conf->level == 6 && s.to_write && s.failed)
+ || (s.syncing && (s.uptodate + s.compute < disks))
+ || s.replacing
+ || s.expanding)
+ handle_stripe_fill(sh, &s, disks);
+
/* Now to consider new write requests and what else, if anything
* should be read. We do not handle new writes when:
* 1/ A 'write' operation (copy+xor) is already in flight.
@@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev)
* discard data disk but write parity disk
*/
stripe = stripe * PAGE_SIZE;
+ /* Round up to power of 2, as discard handling
+ * currently assumes that */
+ while ((stripe-1) & stripe)
+ stripe = (stripe | (stripe-1)) + 1;
mddev->queue->limits.discard_alignment = stripe;
mddev->queue->limits.discard_granularity = stripe;
/*
diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c
index 262dfa503c2a..b551ca350e00 100644
--- a/drivers/media/dvb-frontends/stv0900_core.c
+++ b/drivers/media/dvb-frontends/stv0900_core.c
@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
{
u32 m_div, clk_sel;
- dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
- intp->quartz);
-
if (intp == NULL)
return STV0900_INVALID_HANDLE;
if (intp->errs)
return STV0900_I2C_ERROR;
+ dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+ intp->quartz);
+
clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
m_div = ((clk_sel * mclk) / intp->quartz) - 1;
stv0900_write_bits(intp, F0900_M_DIV, m_div);
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 109bc9b12e74..05f8950f6f91 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
/* ADV7604 system clock frequency */
#define ADV7604_fsc (28636360)
-#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
- (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
/*
**********************************************************************
@@ -68,7 +67,7 @@ struct adv7604_state {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler hdl;
- enum adv7604_prim_mode prim_mode;
+ enum adv7604_mode mode;
struct v4l2_dv_timings timings;
u8 edid[256];
unsigned edid_blocks;
@@ -77,6 +76,7 @@ struct adv7604_state {
struct workqueue_struct *work_queues;
struct delayed_work delayed_work_enable_hotplug;
bool connector_hdmi;
+ bool restart_stdi_once;
/* i2c clients */
struct i2c_client *i2c_avlink;
@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_CEA_720X576P50,
V4L2_DV_BT_CEA_1280X720P24,
V4L2_DV_BT_CEA_1280X720P25,
- V4L2_DV_BT_CEA_1280X720P30,
V4L2_DV_BT_CEA_1280X720P50,
V4L2_DV_BT_CEA_1280X720P60,
V4L2_DV_BT_CEA_1920X1080P24,
@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_CEA_1920X1080P50,
V4L2_DV_BT_CEA_1920X1080P60,
+ /* sorted by DMT ID */
V4L2_DV_BT_DMT_640X350P85,
V4L2_DV_BT_DMT_640X400P85,
V4L2_DV_BT_DMT_720X400P85,
@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
{ },
};
+struct adv7604_video_standards {
+ struct v4l2_dv_timings timings;
+ u8 vid_std;
+ u8 v_freq;
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
+ /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
+ { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+ { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
+ { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
+ { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+ { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+ { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+ { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+ { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+ /* TODO add 1920x1080P60_RB (CVT timing) */
+ { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
+ { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+ { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+ { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+ { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
+ { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
+ { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
+ { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
+ { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
+ /* TODO add 1600X1200P60_RB (not a DMT timing) */
+ { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
+ { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
+ { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
+ { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
+ { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+ { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
+ { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
+ { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+ { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+ { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+ { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+ { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+ { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
+ { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+ { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+ { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+ { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+ { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+ { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+ { },
+};
+
/* ----------------------------------------------------------------------- */
static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
((io_read(sd, 0x6f) & 0x10) >> 4));
}
-static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
+ u8 prim_mode,
+ const struct adv7604_video_standards *predef_vid_timings,
+ const struct v4l2_dv_timings *timings)
+{
+ struct adv7604_state *state = to_state(sd);
+ int i;
+
+ for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
+ if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
+ DIGITAL_INPUT ? 250000 : 1000000))
+ continue;
+ io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
+ io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
+ prim_mode); /* v_freq and prim mode */
+ return 0;
+ }
+
+ return -1;
+}
+
+static int configure_predefined_video_timings(struct v4l2_subdev *sd,
+ struct v4l2_dv_timings *timings)
{
+ struct adv7604_state *state = to_state(sd);
+ int err;
+
+ v4l2_dbg(1, debug, sd, "%s", __func__);
+
+ /* reset to default values */
+ io_write(sd, 0x16, 0x43);
+ io_write(sd, 0x17, 0x5a);
+ /* disable embedded syncs for auto graphics mode */
+ cp_write_and_or(sd, 0x81, 0xef, 0x00);
+ cp_write(sd, 0x8f, 0x00);
+ cp_write(sd, 0x90, 0x00);
+ cp_write(sd, 0xa2, 0x00);
+ cp_write(sd, 0xa3, 0x00);
+ cp_write(sd, 0xa4, 0x00);
+ cp_write(sd, 0xa5, 0x00);
+ cp_write(sd, 0xa6, 0x00);
+ cp_write(sd, 0xa7, 0x00);
+ cp_write(sd, 0xab, 0x00);
+ cp_write(sd, 0xac, 0x00);
+
+ switch (state->mode) {
+ case ADV7604_MODE_COMP:
+ case ADV7604_MODE_GR:
+ err = find_and_set_predefined_video_timings(sd,
+ 0x01, adv7604_prim_mode_comp, timings);
+ if (err)
+ err = find_and_set_predefined_video_timings(sd,
+ 0x02, adv7604_prim_mode_gr, timings);
+ break;
+ case ADV7604_MODE_HDMI:
+ err = find_and_set_predefined_video_timings(sd,
+ 0x05, adv7604_prim_mode_hdmi_comp, timings);
+ if (err)
+ err = find_and_set_predefined_video_timings(sd,
+ 0x06, adv7604_prim_mode_hdmi_gr, timings);
+ break;
+ default:
+ v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+ __func__, state->mode);
+ err = -1;
+ break;
+ }
+
+
+ return err;
+}
+
+static void configure_custom_video_timings(struct v4l2_subdev *sd,
+ const struct v4l2_bt_timings *bt)
+{
+ struct adv7604_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- u32 width = htotal(timings);
- u32 height = vtotal(timings);
- u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
- ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+ u32 width = htotal(bt);
+ u32 height = vtotal(bt);
+ u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
+ u16 cp_start_eav = width - bt->hfrontporch;
+ u16 cp_start_vbi = height - bt->vfrontporch;
+ u16 cp_end_vbi = bt->vsync + bt->vbackporch;
+ u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
+ ((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
+ const u8 pll[2] = {
+ 0xc0 | ((width >> 8) & 0x1f),
+ width & 0xff
+ };
v4l2_dbg(2, debug, sd, "%s\n", __func__);
- cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); /* CH1_FR_LL */
- cp_write(sd, 0x90, ch1_fr_ll & 0xff); /* CH1_FR_LL */
- cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
- cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
- /* TODO support interlaced */
- cp_write(sd, 0x91, 0x10); /* INTERLACED */
-
- /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
- if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
- u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
- const u8 pll[2] = {
- (0xc0 | ((width >> 8) & 0x1f)),
- (width & 0xff)
- };
+ switch (state->mode) {
+ case ADV7604_MODE_COMP:
+ case ADV7604_MODE_GR:
+ /* auto graphics */
+ io_write(sd, 0x00, 0x07); /* video std */
+ io_write(sd, 0x01, 0x02); /* prim mode */
+ /* enable embedded syncs for auto graphics mode */
+ cp_write_and_or(sd, 0x81, 0xef, 0x10);
+ /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
/* IO-map reg. 0x16 and 0x17 should be written in sequence */
if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
- return;
+ break;
}
/* active video - horizontal timing */
- cp_start_sav = timings->hsync + timings->hbackporch - 4;
- cp_start_eav = width - timings->hfrontporch;
cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
- cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+ cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
+ ((cp_start_eav >> 8) & 0x0f));
cp_write(sd, 0xa4, cp_start_eav & 0xff);
/* active video - vertical timing */
- cp_start_vbi = height - timings->vfrontporch;
- cp_end_vbi = timings->vsync + timings->vbackporch;
cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
- cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+ cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
+ ((cp_end_vbi >> 8) & 0xf));
cp_write(sd, 0xa7, cp_end_vbi & 0xff);
- } else {
- /* reset to default values */
- io_write(sd, 0x16, 0x43);
- io_write(sd, 0x17, 0x5a);
- cp_write(sd, 0xa2, 0x00);
- cp_write(sd, 0xa3, 0x00);
- cp_write(sd, 0xa4, 0x00);
- cp_write(sd, 0xa5, 0x00);
- cp_write(sd, 0xa6, 0x00);
- cp_write(sd, 0xa7, 0x00);
+ break;
+ case ADV7604_MODE_HDMI:
+ /* set default prim_mode/vid_std for HDMI
+ accoring to [REF_03, c. 4.2] */
+ io_write(sd, 0x00, 0x02); /* video std */
+ io_write(sd, 0x01, 0x06); /* prim mode */
+ break;
+ default:
+ v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+ __func__, state->mode);
+ break;
}
-}
+ cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
+ cp_write(sd, 0x90, ch1_fr_ll & 0xff);
+ cp_write(sd, 0xab, (height >> 4) & 0xff);
+ cp_write(sd, 0xac, (height & 0x0f) << 4);
+}
static void set_rgb_quantization_range(struct v4l2_subdev *sd)
{
@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
/* automatic */
- if ((hdmi_read(sd, 0x05) & 0x80) ||
- (state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
- (state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
- /* receiving HDMI or analog signal */
- io_write_and_or(sd, 0x02, 0x0f, 0xf0);
- } else {
+ if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
/* receiving DVI-D signal */
/* ADV7604 selects RGB limited range regardless of
@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
/* RGB full range (0-255) */
io_write_and_or(sd, 0x02, 0x0f, 0x10);
}
+ } else {
+ /* receiving HDMI or analog signal, set automode */
+ io_write_and_or(sd, 0x02, 0x0f, 0xf0);
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
state->aspect_ratio, timings))
return 0;
- v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
- __func__, stdi->lcf, stdi->bl);
+ v4l2_dbg(2, debug, sd,
+ "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
+ __func__, stdi->lcvs, stdi->lcf, stdi->bl,
+ stdi->hs_pol, stdi->vs_pol);
return -1;
}
@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
adv7604_fill_optional_dv_timings_fields(sd, timings);
} else {
/* find format
- * Since LCVS values are inaccurate (REF_03, page 275-276),
+ * Since LCVS values are inaccurate [REF_03, p. 275-276],
* stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
*/
if (!stdi2dv_timings(sd, &stdi, timings))
@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
stdi.lcvs -= 2;
v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
if (stdi2dv_timings(sd, &stdi, timings)) {
+ /*
+ * The STDI block may measure wrong values, especially
+ * for lcvs and lcf. If the driver can not find any
+ * valid timing, the STDI block is restarted to measure
+ * the video timings again. The function will return an
+ * error, but the restart of STDI will generate a new
+ * STDI interrupt and the format detection process will
+ * restart.
+ */
+ if (state->restart_stdi_once) {
+ v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
+ /* TODO restart STDI for Sync Channel 2 */
+ /* enter one-shot mode */
+ cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+ /* trigger STDI restart */
+ cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+ /* reset to continuous mode */
+ cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+ state->restart_stdi_once = false;
+ return -ENOLINK;
+ }
v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
return -ERANGE;
}
+ state->restart_stdi_once = true;
}
found:
@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
{
struct adv7604_state *state = to_state(sd);
struct v4l2_bt_timings *bt;
+ int err;
if (!timings)
return -EINVAL;
@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
__func__, (u32)bt->pixelclock);
return -ERANGE;
}
+
adv7604_fill_optional_dv_timings_fields(sd, timings);
state->timings = *timings;
- /* freerun */
- configure_free_run(sd, bt);
+ cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+
+ /* Use prim_mode and vid_std when available */
+ err = configure_predefined_video_timings(sd, timings);
+ if (err) {
+ /* custom settings when the video format
+ does not have prim_mode/vid_std */
+ configure_custom_video_timings(sd, bt);
+ }
set_rgb_quantization_range(sd);
@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
return 0;
}
-static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void enable_input(struct v4l2_subdev *sd)
{
- switch (prim_mode) {
- case ADV7604_PRIM_MODE_COMP:
- case ADV7604_PRIM_MODE_RGB:
+ struct adv7604_state *state = to_state(sd);
+
+ switch (state->mode) {
+ case ADV7604_MODE_COMP:
+ case ADV7604_MODE_GR:
/* enable */
io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
break;
- case ADV7604_PRIM_MODE_HDMI_COMP:
- case ADV7604_PRIM_MODE_HDMI_GR:
+ case ADV7604_MODE_HDMI:
/* enable */
hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
break;
default:
- v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
- __func__, prim_mode);
+ v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+ __func__, state->mode);
break;
}
}
@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd)
hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
}
-static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void select_input(struct v4l2_subdev *sd)
{
- switch (prim_mode) {
- case ADV7604_PRIM_MODE_COMP:
- case ADV7604_PRIM_MODE_RGB:
- /* set mode and select free run resolution */
- io_write(sd, 0x00, 0x07); /* video std */
- io_write(sd, 0x01, 0x02); /* prim mode */
- /* enable embedded syncs for auto graphics mode */
- cp_write_and_or(sd, 0x81, 0xef, 0x10);
+ struct adv7604_state *state = to_state(sd);
+ switch (state->mode) {
+ case ADV7604_MODE_COMP:
+ case ADV7604_MODE_GR:
/* reset ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
@@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
break;
- case ADV7604_PRIM_MODE_HDMI_COMP:
- case ADV7604_PRIM_MODE_HDMI_GR:
- /* set mode and select free run resolution */
- /* video std */
- io_write(sd, 0x00,
- (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
- io_write(sd, 0x01, prim_mode); /* prim mode */
- /* disable embedded syncs for auto graphics mode */
- cp_write_and_or(sd, 0x81, 0xef, 0x00);
-
+ case ADV7604_MODE_HDMI:
/* set ADI recommended settings for HDMI: */
/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
@@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
break;
default:
- v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+ v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+ __func__, state->mode);
break;
}
}
@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
- switch (input) {
- case 0:
- /* TODO select HDMI_COMP or HDMI_GR */
- state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
- break;
- case 1:
- state->prim_mode = ADV7604_PRIM_MODE_RGB;
- break;
- case 2:
- state->prim_mode = ADV7604_PRIM_MODE_COMP;
- break;
- default:
- return -EINVAL;
- }
+ state->mode = input;
disable_input(sd);
- select_input(sd, state->prim_mode);
+ select_input(sd);
- enable_input(sd, state->prim_mode);
+ enable_input(sd);
return 0;
}
@@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
v4l2_info(sd, "CP free run: %s\n",
(!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
- v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
- io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+ v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
+ io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
+ (io_read(sd, 0x01) & 0x70) >> 4);
v4l2_info(sd, "-----Video Timings-----\n");
if (read_stdi(sd, &stdi))
@@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold -
- ADI recommended setting [REF_01 c. 2.3.3] */
+ ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold -
- ADI recommended setting [REF_01 c. 2.3.3] */
+ ADI recommended setting [REF_01, c. 2.3.3] */
cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
for digital formats */
@@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
- state->prim_mode = pdata->prim_mode;
- select_input(sd, pdata->prim_mode);
-
- enable_input(sd, pdata->prim_mode);
-
/* interrupts */
io_write(sd, 0x40, 0xc2); /* Configure INT1 */
io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client,
v4l2_err(sd, "failed to create all i2c clients\n");
goto err_i2c;
}
+ state->restart_stdi_once = true;
/* work queues */
state->work_queues = create_singlethread_workqueue(client->name);
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index 13057b966ee9..333ef178d6fb 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
if (ret & 1) /* Autoexposure */
ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
rect.height + mt9v022->y_skip_top + 43);
- else
- ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
- rect.height + mt9v022->y_skip_top + 43);
+ /*
+ * If autoexposure is off, there is no need to set
+ * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off
+ * only if the user has set exposure manually, using the
+ * V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL.
+ * In this case the register MT9V022_TOTAL_SHUTTER_WIDTH
+ * already contains the correct value.
+ */
}
/* Setup frame format: defaults apart from width and height */
if (!ret)
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index bfec9e65aefb..19cbb12a12a2 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
static const struct of_device_id exynos_gsc_match[] = {
- { .compatible = "samsung,exynos5250-gsc",
- .data = &gsc_v_100_drvdata, },
+ {
+ .compatible = "samsung,exynos5-gsc",
+ .data = &gsc_v_100_drvdata,
+ },
{},
};
MODULE_DEVICE_TABLE(of, exynos_gsc_match);
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index 3c7f00577bd9..c065d040ed94 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -657,8 +657,7 @@ static int gsc_m2m_release(struct file *file)
pr_debug("pid: %d, state: 0x%lx, refcnt= %d",
task_pid_nr(current), gsc->state, gsc->m2m.refcnt);
- if (mutex_lock_interruptible(&gsc->lock))
- return -ERESTARTSYS;
+ mutex_lock(&gsc->lock);
v4l2_m2m_ctx_release(ctx->m2m_ctx);
gsc_ctrls_delete(ctx);
@@ -732,6 +731,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc)
gsc->vdev.ioctl_ops = &gsc_m2m_ioctl_ops;
gsc->vdev.release = video_device_release_empty;
gsc->vdev.lock = &gsc->lock;
+ gsc->vdev.vfl_dir = VFL_DIR_M2M;
snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
GSC_MODULE_NAME, gsc->id);
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h
index 533e9947a925..4678f9a6a4fd 100644
--- a/drivers/media/platform/exynos-gsc/gsc-regs.h
+++ b/drivers/media/platform/exynos-gsc/gsc-regs.h
@@ -40,10 +40,10 @@
#define GSC_IN_ROT_YFLIP (2 << 16)
#define GSC_IN_ROT_XFLIP (1 << 16)
#define GSC_IN_RGB_TYPE_MASK (3 << 14)
-#define GSC_IN_RGB_HD_WIDE (3 << 14)
-#define GSC_IN_RGB_HD_NARROW (2 << 14)
-#define GSC_IN_RGB_SD_WIDE (1 << 14)
-#define GSC_IN_RGB_SD_NARROW (0 << 14)
+#define GSC_IN_RGB_HD_NARROW (3 << 14)
+#define GSC_IN_RGB_HD_WIDE (2 << 14)
+#define GSC_IN_RGB_SD_NARROW (1 << 14)
+#define GSC_IN_RGB_SD_WIDE (0 << 14)
#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)
#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13)
#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13)
@@ -85,10 +85,10 @@
#define GSC_OUT_GLOBAL_ALPHA_MASK (0xff << 24)
#define GSC_OUT_GLOBAL_ALPHA(x) ((x) << 24)
#define GSC_OUT_RGB_TYPE_MASK (3 << 10)
-#define GSC_OUT_RGB_HD_NARROW (3 << 10)
-#define GSC_OUT_RGB_HD_WIDE (2 << 10)
-#define GSC_OUT_RGB_SD_NARROW (1 << 10)
-#define GSC_OUT_RGB_SD_WIDE (0 << 10)
+#define GSC_OUT_RGB_HD_WIDE (3 << 10)
+#define GSC_OUT_RGB_HD_NARROW (2 << 10)
+#define GSC_OUT_RGB_SD_WIDE (1 << 10)
+#define GSC_OUT_RGB_SD_NARROW (0 << 10)
#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)
#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9)
#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9)
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 60181ab96063..aa9df9d71a7b 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
}
static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
+ struct v4l2_event_subscription *sub)
{
if (sub->type != V4L2_EVENT_FRAME_SYNC)
return -EINVAL;
@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
}
static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
+ struct v4l2_event_subscription *sub)
{
return v4l2_event_unsubscribe(fh, sub);
}
diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c
index d7ac76b5c2ae..b8640be692f1 100644
--- a/drivers/media/platform/omap3isp/ispstat.c
+++ b/drivers/media/platform/omap3isp/ispstat.c
@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
+ struct v4l2_event_subscription *sub)
{
struct ispstat *stat = v4l2_get_subdevdata(subdev);
@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
+ struct v4l2_event_subscription *sub)
{
return v4l2_event_unsubscribe(fh, sub);
}
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index a6fe653eb237..9b7c8654dc8a 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
void omap3isp_stat_cleanup(struct ispstat *stat);
int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub);
+ struct v4l2_event_subscription *sub);
int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub);
+ struct v4l2_event_subscription *sub);
int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
int omap3isp_stat_busy(struct ispstat *stat);
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index a0b737fecf13..75cd309035f9 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
}
static int
-isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
{
struct isp_video *video = video_drvdata(file);
struct v4l2_subdev *subdev;
diff --git a/drivers/media/platform/s5p-fimc/Kconfig b/drivers/media/platform/s5p-fimc/Kconfig
index 8f090a8f270e..c16b20d86ed2 100644
--- a/drivers/media/platform/s5p-fimc/Kconfig
+++ b/drivers/media/platform/s5p-fimc/Kconfig
@@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC
config VIDEO_S5P_MIPI_CSIS
tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
depends on REGULATOR
+ select S5P_SETUP_MIPIPHY
help
This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
receiver (MIPI-CSIS) devices.
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index 367efd164d0f..891ee873c62b 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -556,8 +556,7 @@ static int fimc_capture_close(struct file *file)
dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
- if (mutex_lock_interruptible(&fimc->lock))
- return -ERESTARTSYS;
+ mutex_lock(&fimc->lock);
if (--fimc->vid_cap.refcnt == 0) {
clear_bit(ST_CAPT_BUSY, &fimc->state);
@@ -1736,7 +1735,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
q->mem_ops = &vb2_dma_contig_memops;
q->buf_struct_size = sizeof(struct fimc_vid_buffer);
- vb2_queue_init(q);
+ ret = vb2_queue_init(q);
+ if (ret)
+ goto err_ent;
vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
@@ -1772,9 +1773,13 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
+ fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
+
ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
- if (ret)
+ if (ret) {
fimc_unregister_m2m_device(fimc);
+ fimc->pipeline_ops = NULL;
+ }
return ret;
}
@@ -1791,6 +1796,7 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
if (video_is_registered(&fimc->vid_cap.vfd)) {
video_unregister_device(&fimc->vid_cap.vfd);
media_entity_cleanup(&fimc->vid_cap.vfd.entity);
+ fimc->pipeline_ops = NULL;
}
kfree(fimc->vid_cap.ctx);
fimc->vid_cap.ctx = NULL;
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index 70bcf39de879..1b309a72f09f 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -491,8 +491,7 @@ static int fimc_lite_close(struct file *file)
struct fimc_lite *fimc = video_drvdata(file);
int ret;
- if (mutex_lock_interruptible(&fimc->lock))
- return -ERESTARTSYS;
+ mutex_lock(&fimc->lock);
if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
clear_bit(ST_FLITE_IN_USE, &fimc->state);
@@ -1253,7 +1252,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
q->buf_struct_size = sizeof(struct flite_buffer);
q->drv_priv = fimc;
- vb2_queue_init(q);
+ ret = vb2_queue_init(q);
+ if (ret < 0)
+ return ret;
fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
@@ -1261,10 +1262,12 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
return ret;
video_set_drvdata(vfd, fimc);
+ fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
media_entity_cleanup(&vfd->entity);
+ fimc->pipeline_ops = NULL;
return ret;
}
@@ -1283,6 +1286,7 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
if (video_is_registered(&fimc->vfd)) {
video_unregister_device(&fimc->vfd);
media_entity_cleanup(&fimc->vfd.entity);
+ fimc->pipeline_ops = NULL;
}
}
diff --git a/drivers/media/platform/s5p-fimc/fimc-m2m.c b/drivers/media/platform/s5p-fimc/fimc-m2m.c
index 4500e44f6857..62afed3162ea 100644
--- a/drivers/media/platform/s5p-fimc/fimc-m2m.c
+++ b/drivers/media/platform/s5p-fimc/fimc-m2m.c
@@ -718,8 +718,7 @@ static int fimc_m2m_release(struct file *file)
dbg("pid: %d, state: 0x%lx, refcnt= %d",
task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
- if (mutex_lock_interruptible(&fimc->lock))
- return -ERESTARTSYS;
+ mutex_lock(&fimc->lock);
v4l2_m2m_ctx_release(ctx->m2m_ctx);
fimc_ctrls_delete(ctx);
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 80ada5882f62..0531ab70a94c 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
static int fimc_register_callback(struct device *dev, void *p)
{
struct fimc_dev *fimc = dev_get_drvdata(dev);
- struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+ struct v4l2_subdev *sd;
struct fimc_md *fmd = p;
- int ret = 0;
-
- if (!fimc || !fimc->pdev)
- return 0;
+ int ret;
- if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+ if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
return 0;
- fimc->pipeline_ops = &fimc_pipeline_ops;
- fmd->fimc[fimc->pdev->id] = fimc;
+ sd = &fimc->vid_cap.subdev;
sd->grp_id = FIMC_GROUP_ID;
+ v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (ret) {
v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
fimc->id, ret);
+ return ret;
}
- return ret;
+ fmd->fimc[fimc->id] = fimc;
+ return 0;
}
static int fimc_lite_register_callback(struct device *dev, void *p)
{
struct fimc_lite *fimc = dev_get_drvdata(dev);
- struct v4l2_subdev *sd = &fimc->subdev;
struct fimc_md *fmd = p;
int ret;
- if (fimc == NULL)
+ if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
return 0;
- if (fimc->index >= FIMC_LITE_MAX_DEVS)
- return 0;
-
- fimc->pipeline_ops = &fimc_pipeline_ops;
- fmd->fimc_lite[fimc->index] = fimc;
- sd->grp_id = FLITE_GROUP_ID;
+ fimc->subdev.grp_id = FLITE_GROUP_ID;
+ v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops);
- ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+ ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
if (ret) {
v4l2_err(&fmd->v4l2_dev,
"Failed to register FIMC-LITE.%d (%d)\n",
fimc->index, ret);
+ return ret;
}
- return ret;
+
+ fmd->fimc_lite[fimc->index] = fimc;
+ return 0;
}
static int csis_register_callback(struct device *dev, void *p)
@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p)
v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
id = pdev->id < 0 ? 0 : pdev->id;
- fmd->csis[id].sd = sd;
sd->grp_id = CSIS_GROUP_ID;
+
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
- if (ret)
+ if (!ret)
+ fmd->csis[id].sd = sd;
+ else
v4l2_err(&fmd->v4l2_dev,
"Failed to register CSIS subdevice: %d\n", ret);
return ret;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 130f4ac8649e..3afe879d54d7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -381,11 +381,8 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
get_consumed_stream, dev);
if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
- s5p_mfc_hw_call(dev->mfc_ops,
- get_dec_frame_type, dev) ==
- S5P_FIMV_DECODE_FRAME_P_FRAME
- && ctx->consumed_stream + STUFF_BYTE <
- src_buf->b->v4l2_planes[0].bytesused) {
+ ctx->consumed_stream + STUFF_BYTE <
+ src_buf->b->v4l2_planes[0].bytesused) {
/* Run MFC again on the same buffer */
mfc_debug(2, "Running again the same buffer\n");
ctx->after_packed_pb = 1;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 50b5bee3c44e..3a8cfd9fc1bd 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -1762,7 +1762,7 @@ int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
{
- return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+ return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6);
}
int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 85fd312f0a82..a1c87f0ceaab 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
/* Assume a dull encoder, do all the work ourselves. */
static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
{
+ struct v4l2_crop a_writable = *a;
struct video_device *vdev = video_devdata(file);
struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
- struct v4l2_rect *rect = &a->c;
+ struct v4l2_rect *rect = &a_writable.c;
struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
struct v4l2_pix_format *pix = &vou_dev->pix;
struct sh_vou_geometry geo;
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c
index bbe70991d30b..032b8c9097f9 100644
--- a/drivers/media/platform/soc_camera/mx1_camera.c
+++ b/drivers/media/platform/soc_camera/mx1_camera.c
@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
pcdev->icd = NULL;
}
-static int mx1_camera_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
- return v4l2_subdev_call(sd, video, s_crop, a);
-}
-
static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
.add = mx1_camera_add_device,
.remove = mx1_camera_remove_device,
.set_bus_param = mx1_camera_set_bus_param,
- .set_crop = mx1_camera_set_crop,
.set_fmt = mx1_camera_set_fmt,
.try_fmt = mx1_camera_try_fmt,
.init_videobuf = mx1_camera_init_videobuf,
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 9fd9d1c5b218..9a55f4c4c7f4 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
bytesperline = soc_mbus_bytes_per_line(icd->user_width,
icd->current_fmt->host_fmt);
- if (bytesperline < 0)
+ if (bytesperline < 0) {
+ spin_unlock_irqrestore(&pcdev->lock, flags);
return bytesperline;
+ }
/*
* I didn't manage to properly enable/disable the prp
@@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
pcdev->discard_size, &pcdev->discard_buffer_dma,
GFP_KERNEL);
- if (!pcdev->discard_buffer)
+ if (!pcdev->discard_buffer) {
+ spin_unlock_irqrestore(&pcdev->lock, flags);
return -ENOMEM;
+ }
pcdev->buf_discard[0].discard = true;
list_add_tail(&pcdev->buf_discard[0].queue,
@@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
}
static int mx2_camera_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+ const struct v4l2_crop *a)
{
- struct v4l2_rect *rect = &a->c;
+ struct v4l2_crop a_writable = *a;
+ struct v4l2_rect *rect = &a_writable.c;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_mbus_framefmt mf;
int ret;
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 3557ac97e430..261f6e9e1b17 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width)
* default g_crop and cropcap from soc_camera.c
*/
static int mx3_camera_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+ const struct v4l2_crop *a)
{
- struct v4l2_rect *rect = &a->c;
+ struct v4l2_crop a_writable = *a;
+ struct v4l2_rect *rect = &a_writable.c;
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index fa08c7695ccb..13636a585106 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
}
static int omap1_cam_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *crop)
+ const struct v4l2_crop *crop)
{
- struct v4l2_rect *rect = &crop->c;
+ const struct v4l2_rect *rect = &crop->c;
const struct soc_camera_format_xlate *xlate = icd->current_fmt;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 1e3776d08dac..3434ffe79c6e 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height)
}
static int pxa_camera_set_crop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+ const struct v4l2_crop *a)
{
- struct v4l2_rect *rect = &a->c;
+ const struct v4l2_rect *rect = &a->c;
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct pxa_camera_dev *pcdev = ici->priv;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 0a24253dcda2..2d8861c0e8f2 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
}
/* Check if any dimension of r1 is smaller than respective one of r2 */
-static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
{
return r1->width < r2->width || r1->height < r2->height;
}
/* Check if r1 fails to cover r2 */
-static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
{
return r1->left > r2->left || r1->top > r2->top ||
r1->left + r1->width < r2->left + r2->width ||
@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
* 3. if (2) failed, try to request the maximum image
*/
static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
- const struct v4l2_crop *cam_crop)
+ struct v4l2_crop *cam_crop)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd,
static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
const struct v4l2_crop *a)
{
- struct v4l2_rect *rect = &a->c;
+ struct v4l2_crop a_writable = *a;
+ const struct v4l2_rect *rect = &a_writable.c;
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
* 1. - 2. Apply iterative camera S_CROP for new input window, read back
* actual camera rectangle.
*/
- ret = client_s_crop(icd, a, &cam_crop);
+ ret = client_s_crop(icd, &a_writable, &cam_crop);
if (ret < 0)
return ret;
@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
}
static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
- struct v4l2_crop *a)
+ const struct v4l2_crop *a)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index 9859d2a2449b..ba51f65204de 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
/* activate the pid on the device pid filter */
if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
- adap->pid_filtering &&
- adap->props->pid_filter)
+ adap->pid_filtering && adap->props->pid_filter) {
ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
dvbdmxfeed->pid, (count == 1) ? 1 : 0);
- if (ret < 0)
- dev_err(&d->udev->dev, "%s: pid_filter() " \
- "failed=%d\n", KBUILD_MODNAME,
- ret);
+ if (ret < 0)
+ dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+ KBUILD_MODNAME, ret);
+ }
/* start feeding if it is first pid */
if (adap->feed_count == 1 && count == 1) {
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
index 0431beed0ef4..5716662b4834 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
return -EINVAL;
}
- ret = mutex_lock_interruptible(&d->usb_mutex);
- if (ret < 0)
- return ret;
+ mutex_lock(&d->usb_mutex);
dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index adabba8d28bc..093f1acce403 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
&rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
{ DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
&rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+ { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
+ &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
+ { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
+ &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index cc0997a05171..4f7a17fd1aa7 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -42,3 +42,13 @@ config MEMSTICK_R592
To compile this driver as a module, choose M here: the module will
be called r592.
+
+config MEMSTICK_REALTEK_PCI
+ tristate "Realtek PCI-E Memstick Card Interface Driver"
+ depends on MFD_RTSX_PCI
+ help
+ Say Y here to include driver code to support Memstick card interface
+ of Realtek PCI-E card reader
+
+ To compile this driver as a module, choose M here: the module will
+ be called rtsx_pci_ms.
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index 31ba8d378e46..af3459d7686e 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o
obj-$(CONFIG_MEMSTICK_R592) += r592.o
+obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c
new file mode 100644
index 000000000000..f5ddb82dadb7
--- /dev/null
+++ b/drivers/memstick/host/rtsx_pci_ms.c
@@ -0,0 +1,641 @@
+/* Realtek PCI-Express Memstick Card Interface driver
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/memstick.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+struct realtek_pci_ms {
+ struct platform_device *pdev;
+ struct rtsx_pcr *pcr;
+ struct memstick_host *msh;
+ struct memstick_request *req;
+
+ struct mutex host_mutex;
+ struct work_struct handle_req;
+
+ u8 ssc_depth;
+ unsigned int clock;
+ unsigned char ifmode;
+ bool eject;
+};
+
+static inline struct device *ms_dev(struct realtek_pci_ms *host)
+{
+ return &(host->pdev->dev);
+}
+
+static inline void ms_clear_error(struct realtek_pci_ms *host)
+{
+ rtsx_pci_write_register(host->pcr, CARD_STOP,
+ MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
+}
+
+#ifdef DEBUG
+
+static void ms_print_debug_regs(struct realtek_pci_ms *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ u16 i;
+ u8 *ptr;
+
+ /* Print MS host internal registers */
+ rtsx_pci_init_cmd(pcr);
+ for (i = 0xFD40; i <= 0xFD44; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+ for (i = 0xFD52; i <= 0xFD69; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+ rtsx_pci_send_cmd(pcr, 100);
+
+ ptr = rtsx_pci_get_cmd_data(pcr);
+ for (i = 0xFD40; i <= 0xFD44; i++)
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+ for (i = 0xFD52; i <= 0xFD69; i++)
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+}
+
+#else
+
+#define ms_print_debug_regs(host)
+
+#endif
+
+static int ms_power_on(struct realtek_pci_ms *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_48_MS);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
+ MS_CLK_EN, MS_CLK_EN);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_MS_CARD);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_power_on(pcr, RTSX_MS_CARD);
+ if (err < 0)
+ return err;
+
+ /* Wait ms power stable */
+ msleep(150);
+
+ err = rtsx_pci_write_register(pcr, CARD_OE,
+ MS_OUTPUT_EN, MS_OUTPUT_EN);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int ms_power_off(struct realtek_pci_ms *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
+ if (err < 0)
+ return err;
+
+ return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
+}
+
+static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir,
+ u8 tpc, u8 cfg, struct scatterlist *sg)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+ unsigned int length = sg->length;
+ u16 sec_cnt = (u16)(length / 512);
+ u8 val, trans_mode, dma_dir;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
+ __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
+ length);
+
+ if (data_dir == READ) {
+ dma_dir = DMA_DIR_FROM_CARD;
+ trans_mode = MS_TM_AUTO_READ;
+ } else {
+ dma_dir = DMA_DIR_TO_CARD;
+ trans_mode = MS_TM_AUTO_WRITE;
+ }
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
+ 0xFF, (u8)(sec_cnt >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
+ 0xFF, (u8)sec_cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+ DMA_DONE_INT, DMA_DONE_INT);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+ 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, RING_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | trans_mode);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+
+ rtsx_pci_send_cmd_no_wait(pcr);
+
+ err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000);
+ if (err < 0) {
+ ms_clear_error(host);
+ return err;
+ }
+
+ rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+ if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
+ return -EIO;
+
+ return 0;
+}
+
+static int ms_write_bytes(struct realtek_pci_ms *host, u8 tpc,
+ u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err, i;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+ if (!data)
+ return -EINVAL;
+
+ rtsx_pci_init_cmd(pcr);
+
+ for (i = 0; i < cnt; i++)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ PPBUF_BASE2 + i, 0xFF, data[i]);
+ if (cnt % 2)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ PPBUF_BASE2 + i, 0xFF, 0xFF);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+ if (int_reg)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 5000);
+ if (err < 0) {
+ u8 val;
+
+ rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+ dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+ if (int_reg)
+ *int_reg = val & 0x0F;
+
+ ms_print_debug_regs(host);
+
+ ms_clear_error(host);
+
+ if (!(tpc & 0x08)) {
+ if (val & MS_CRC16_ERR)
+ return -EIO;
+ } else {
+ if (!(val & 0x80)) {
+ if (val & (MS_INT_ERR | MS_INT_CMDNK))
+ return -EIO;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ if (int_reg) {
+ u8 *ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+ *int_reg = *ptr & 0x0F;
+ }
+
+ return 0;
+}
+
+static int ms_read_bytes(struct realtek_pci_ms *host, u8 tpc,
+ u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err, i;
+ u8 *ptr;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+ if (!data)
+ return -EINVAL;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+ for (i = 0; i < cnt - 1; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+ if (cnt % 2)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
+ else
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD,
+ PPBUF_BASE2 + cnt - 1, 0, 0);
+ if (int_reg)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 5000);
+ if (err < 0) {
+ u8 val;
+
+ rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val);
+ dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+ if (int_reg)
+ *int_reg = val & 0x0F;
+
+ ms_print_debug_regs(host);
+
+ ms_clear_error(host);
+
+ if (!(tpc & 0x08)) {
+ if (val & MS_CRC16_ERR)
+ return -EIO;
+ } else {
+ if (!(val & 0x80)) {
+ if (val & (MS_INT_ERR | MS_INT_CMDNK))
+ return -EIO;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+ for (i = 0; i < cnt; i++)
+ data[i] = *ptr++;
+
+ if (int_reg)
+ *int_reg = *ptr & 0x0F;
+
+ return 0;
+}
+
+static int rtsx_pci_ms_issue_cmd(struct realtek_pci_ms *host)
+{
+ struct memstick_request *req = host->req;
+ int err = 0;
+ u8 cfg = 0, int_reg;
+
+ dev_dbg(ms_dev(host), "%s\n", __func__);
+
+ if (req->need_card_int) {
+ if (host->ifmode != MEMSTICK_SERIAL)
+ cfg = WAIT_INT;
+ }
+
+ if (req->long_data) {
+ err = ms_transfer_data(host, req->data_dir,
+ req->tpc, cfg, &(req->sg));
+ } else {
+ if (req->data_dir == READ) {
+ err = ms_read_bytes(host, req->tpc, cfg,
+ req->data_len, req->data, &int_reg);
+ } else {
+ err = ms_write_bytes(host, req->tpc, cfg,
+ req->data_len, req->data, &int_reg);
+ }
+ }
+ if (err < 0)
+ return err;
+
+ if (req->need_card_int && (host->ifmode == MEMSTICK_SERIAL)) {
+ err = ms_read_bytes(host, MS_TPC_GET_INT,
+ NO_WAIT_INT, 1, &int_reg, NULL);
+ if (err < 0)
+ return err;
+ }
+
+ if (req->need_card_int) {
+ dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", int_reg);
+
+ if (int_reg & MS_INT_CMDNK)
+ req->int_reg |= MEMSTICK_INT_CMDNAK;
+ if (int_reg & MS_INT_BREQ)
+ req->int_reg |= MEMSTICK_INT_BREQ;
+ if (int_reg & MS_INT_ERR)
+ req->int_reg |= MEMSTICK_INT_ERR;
+ if (int_reg & MS_INT_CED)
+ req->int_reg |= MEMSTICK_INT_CED;
+ }
+
+ return 0;
+}
+
+static void rtsx_pci_ms_handle_req(struct work_struct *work)
+{
+ struct realtek_pci_ms *host = container_of(work,
+ struct realtek_pci_ms, handle_req);
+ struct rtsx_pcr *pcr = host->pcr;
+ struct memstick_host *msh = host->msh;
+ int rc;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ rtsx_pci_switch_clock(host->pcr, host->clock, host->ssc_depth,
+ false, true, false);
+ rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, MS_MOD_SEL);
+ rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_48_MS);
+
+ if (!host->req) {
+ do {
+ rc = memstick_next_req(msh, &host->req);
+ dev_dbg(ms_dev(host), "next req %d\n", rc);
+
+ if (!rc)
+ host->req->error = rtsx_pci_ms_issue_cmd(host);
+ } while (!rc);
+ }
+
+ mutex_unlock(&pcr->pcr_mutex);
+}
+
+static void rtsx_pci_ms_request(struct memstick_host *msh)
+{
+ struct realtek_pci_ms *host = memstick_priv(msh);
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ schedule_work(&host->handle_req);
+}
+
+static int rtsx_pci_ms_set_param(struct memstick_host *msh,
+ enum memstick_param param, int value)
+{
+ struct realtek_pci_ms *host = memstick_priv(msh);
+ struct rtsx_pcr *pcr = host->pcr;
+ unsigned int clock = 0;
+ u8 ssc_depth = 0;
+ int err;
+
+ dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
+ __func__, param, value);
+
+ switch (param) {
+ case MEMSTICK_POWER:
+ if (value == MEMSTICK_POWER_ON)
+ err = ms_power_on(host);
+ else if (value == MEMSTICK_POWER_OFF)
+ err = ms_power_off(host);
+ else
+ return -EINVAL;
+ break;
+
+ case MEMSTICK_INTERFACE:
+ if (value == MEMSTICK_SERIAL) {
+ clock = 19000000;
+ ssc_depth = RTSX_SSC_DEPTH_500K;
+
+ err = rtsx_pci_write_register(pcr, MS_CFG,
+ 0x18, MS_BUS_WIDTH_1);
+ if (err < 0)
+ return err;
+ } else if (value == MEMSTICK_PAR4) {
+ clock = 39000000;
+ ssc_depth = RTSX_SSC_DEPTH_1M;
+
+ err = rtsx_pci_write_register(pcr, MS_CFG,
+ 0x58, MS_BUS_WIDTH_4 | PUSH_TIME_ODD);
+ if (err < 0)
+ return err;
+ } else {
+ return -EINVAL;
+ }
+
+ err = rtsx_pci_switch_clock(pcr, clock,
+ ssc_depth, false, true, false);
+ if (err < 0)
+ return err;
+
+ host->ssc_depth = ssc_depth;
+ host->clock = clock;
+ host->ifmode = value;
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int rtsx_pci_ms_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+ struct memstick_host *msh = host->msh;
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ memstick_suspend_host(msh);
+ return 0;
+}
+
+static int rtsx_pci_ms_resume(struct platform_device *pdev)
+{
+ struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+ struct memstick_host *msh = host->msh;
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ memstick_resume_host(msh);
+ return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_pci_ms_suspend NULL
+#define rtsx_pci_ms_resume NULL
+
+#endif /* CONFIG_PM */
+
+static void rtsx_pci_ms_card_event(struct platform_device *pdev)
+{
+ struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+
+ memstick_detect_change(host->msh);
+}
+
+static int rtsx_pci_ms_drv_probe(struct platform_device *pdev)
+{
+ struct memstick_host *msh;
+ struct realtek_pci_ms *host;
+ struct rtsx_pcr *pcr;
+ struct pcr_handle *handle = pdev->dev.platform_data;
+ int rc;
+
+ if (!handle)
+ return -ENXIO;
+
+ pcr = handle->pcr;
+ if (!pcr)
+ return -ENXIO;
+
+ dev_dbg(&(pdev->dev),
+ ": Realtek PCI-E Memstick controller found\n");
+
+ msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
+ if (!msh)
+ return -ENOMEM;
+
+ host = memstick_priv(msh);
+ host->pcr = pcr;
+ host->msh = msh;
+ host->pdev = pdev;
+ platform_set_drvdata(pdev, host);
+ pcr->slots[RTSX_MS_CARD].p_dev = pdev;
+ pcr->slots[RTSX_MS_CARD].card_event = rtsx_pci_ms_card_event;
+
+ mutex_init(&host->host_mutex);
+
+ INIT_WORK(&host->handle_req, rtsx_pci_ms_handle_req);
+ msh->request = rtsx_pci_ms_request;
+ msh->set_param = rtsx_pci_ms_set_param;
+ msh->caps = MEMSTICK_CAP_PAR4;
+
+ rc = memstick_add_host(msh);
+ if (rc) {
+ memstick_free_host(msh);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int rtsx_pci_ms_drv_remove(struct platform_device *pdev)
+{
+ struct realtek_pci_ms *host = platform_get_drvdata(pdev);
+ struct rtsx_pcr *pcr;
+ struct memstick_host *msh;
+ int rc;
+
+ if (!host)
+ return 0;
+
+ pcr = host->pcr;
+ pcr->slots[RTSX_MS_CARD].p_dev = NULL;
+ pcr->slots[RTSX_MS_CARD].card_event = NULL;
+ msh = host->msh;
+ host->eject = true;
+
+ mutex_lock(&host->host_mutex);
+ if (host->req) {
+ dev_dbg(&(pdev->dev),
+ "%s: Controller removed during transfer\n",
+ dev_name(&msh->dev));
+
+ rtsx_pci_complete_unfinished_transfer(pcr);
+
+ host->req->error = -ENOMEDIUM;
+ do {
+ rc = memstick_next_req(msh, &host->req);
+ if (!rc)
+ host->req->error = -ENOMEDIUM;
+ } while (!rc);
+ }
+ mutex_unlock(&host->host_mutex);
+
+ memstick_remove_host(msh);
+ memstick_free_host(msh);
+
+ platform_set_drvdata(pdev, NULL);
+
+ dev_dbg(&(pdev->dev),
+ ": Realtek PCI-E Memstick controller has been removed\n");
+
+ return 0;
+}
+
+static struct platform_device_id rtsx_pci_ms_ids[] = {
+ {
+ .name = DRV_NAME_RTSX_PCI_MS,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, rtsx_pci_ms_ids);
+
+static struct platform_driver rtsx_pci_ms_driver = {
+ .probe = rtsx_pci_ms_drv_probe,
+ .remove = rtsx_pci_ms_drv_remove,
+ .id_table = rtsx_pci_ms_ids,
+ .suspend = rtsx_pci_ms_suspend,
+ .resume = rtsx_pci_ms_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME_RTSX_PCI_MS,
+ },
+};
+module_platform_driver(rtsx_pci_ms_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E Memstick Card Host Driver");
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index ce229ea933d1..391e23e6a647 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -248,7 +248,7 @@ static const struct regmap_irq pm800_irqs[] = {
},
};
-static int __devinit device_gpadc_init(struct pm80x_chip *chip,
+static int device_gpadc_init(struct pm80x_chip *chip,
struct pm80x_platform_data *pdata)
{
struct pm80x_subchip *subchip = chip->subchip;
@@ -315,7 +315,7 @@ out:
return ret;
}
-static int __devinit device_irq_init_800(struct pm80x_chip *chip)
+static int device_irq_init_800(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
@@ -415,7 +415,7 @@ static void pm800_pages_exit(struct pm80x_chip *chip)
}
}
-static int __devinit device_800_init(struct pm80x_chip *chip,
+static int device_800_init(struct pm80x_chip *chip,
struct pm80x_platform_data *pdata)
{
int ret, pmic_id;
@@ -499,7 +499,7 @@ out:
return ret;
}
-static int __devinit pm800_probe(struct i2c_client *client,
+static int pm800_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
@@ -554,7 +554,7 @@ out_init:
return ret;
}
-static int __devexit pm800_remove(struct i2c_client *client)
+static int pm800_remove(struct i2c_client *client)
{
struct pm80x_chip *chip = i2c_get_clientdata(client);
@@ -576,7 +576,7 @@ static struct i2c_driver pm800_driver = {
.pm = &pm80x_pm_ops,
},
.probe = pm800_probe,
- .remove = __devexit_p(pm800_remove),
+ .remove = pm800_remove,
.id_table = pm80x_id_table,
};
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index c20a31136f04..e671230be2b1 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -135,7 +135,7 @@ static struct regmap_irq pm805_irqs[] = {
},
};
-static int __devinit device_irq_init_805(struct pm80x_chip *chip)
+static int device_irq_init_805(struct pm80x_chip *chip)
{
struct regmap *map = chip->regmap;
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
@@ -189,7 +189,7 @@ static struct regmap_irq_chip pm805_irq_chip = {
.ack_base = PM805_INT_STATUS1,
};
-static int __devinit device_805_init(struct pm80x_chip *chip)
+static int device_805_init(struct pm80x_chip *chip)
{
int ret = 0;
unsigned int val;
@@ -232,7 +232,7 @@ out_irq_init:
return ret;
}
-static int __devinit pm805_probe(struct i2c_client *client,
+static int pm805_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
@@ -262,7 +262,7 @@ out_init:
return ret;
}
-static int __devexit pm805_remove(struct i2c_client *client)
+static int pm805_remove(struct i2c_client *client)
{
struct pm80x_chip *chip = i2c_get_clientdata(client);
@@ -281,7 +281,7 @@ static struct i2c_driver pm805_driver = {
.pm = &pm80x_pm_ops,
},
.probe = pm805_probe,
- .remove = __devexit_p(pm805_remove),
+ .remove = pm805_remove,
.id_table = pm80x_id_table,
};
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index cd0bf527d764..1adb355d86d1 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -31,7 +31,7 @@ const struct regmap_config pm80x_regmap_config = {
};
EXPORT_SYMBOL_GPL(pm80x_regmap_config);
-int __devinit pm80x_init(struct i2c_client *client,
+int pm80x_init(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pm80x_chip *chip;
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 8fa86edf70d4..893fc1ba6ead 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -28,111 +28,111 @@
#define INT_STATUS_NUM 3
-static struct resource bk0_resources[] __devinitdata = {
+static struct resource bk0_resources[] = {
{2, 2, "duty cycle", IORESOURCE_REG, },
{3, 3, "always on", IORESOURCE_REG, },
{3, 3, "current", IORESOURCE_REG, },
};
-static struct resource bk1_resources[] __devinitdata = {
+static struct resource bk1_resources[] = {
{4, 4, "duty cycle", IORESOURCE_REG, },
{5, 5, "always on", IORESOURCE_REG, },
{5, 5, "current", IORESOURCE_REG, },
};
-static struct resource bk2_resources[] __devinitdata = {
+static struct resource bk2_resources[] = {
{6, 6, "duty cycle", IORESOURCE_REG, },
{7, 7, "always on", IORESOURCE_REG, },
{5, 5, "current", IORESOURCE_REG, },
};
-static struct resource led0_resources[] __devinitdata = {
+static struct resource led0_resources[] = {
/* RGB1 Red LED */
{0xd, 0xd, "control", IORESOURCE_REG, },
{0xc, 0xc, "blink", IORESOURCE_REG, },
};
-static struct resource led1_resources[] __devinitdata = {
+static struct resource led1_resources[] = {
/* RGB1 Green LED */
{0xe, 0xe, "control", IORESOURCE_REG, },
{0xc, 0xc, "blink", IORESOURCE_REG, },
};
-static struct resource led2_resources[] __devinitdata = {
+static struct resource led2_resources[] = {
/* RGB1 Blue LED */
{0xf, 0xf, "control", IORESOURCE_REG, },
{0xc, 0xc, "blink", IORESOURCE_REG, },
};
-static struct resource led3_resources[] __devinitdata = {
+static struct resource led3_resources[] = {
/* RGB2 Red LED */
{0x9, 0x9, "control", IORESOURCE_REG, },
{0x8, 0x8, "blink", IORESOURCE_REG, },
};
-static struct resource led4_resources[] __devinitdata = {
+static struct resource led4_resources[] = {
/* RGB2 Green LED */
{0xa, 0xa, "control", IORESOURCE_REG, },
{0x8, 0x8, "blink", IORESOURCE_REG, },
};
-static struct resource led5_resources[] __devinitdata = {
+static struct resource led5_resources[] = {
/* RGB2 Blue LED */
{0xb, 0xb, "control", IORESOURCE_REG, },
{0x8, 0x8, "blink", IORESOURCE_REG, },
};
-static struct resource buck1_resources[] __devinitdata = {
+static struct resource buck1_resources[] = {
{0x24, 0x24, "buck set", IORESOURCE_REG, },
};
-static struct resource buck2_resources[] __devinitdata = {
+static struct resource buck2_resources[] = {
{0x25, 0x25, "buck set", IORESOURCE_REG, },
};
-static struct resource buck3_resources[] __devinitdata = {
+static struct resource buck3_resources[] = {
{0x26, 0x26, "buck set", IORESOURCE_REG, },
};
-static struct resource ldo1_resources[] __devinitdata = {
+static struct resource ldo1_resources[] = {
{0x10, 0x10, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo2_resources[] __devinitdata = {
+static struct resource ldo2_resources[] = {
{0x11, 0x11, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo3_resources[] __devinitdata = {
+static struct resource ldo3_resources[] = {
{0x12, 0x12, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo4_resources[] __devinitdata = {
+static struct resource ldo4_resources[] = {
{0x13, 0x13, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo5_resources[] __devinitdata = {
+static struct resource ldo5_resources[] = {
{0x14, 0x14, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo6_resources[] __devinitdata = {
+static struct resource ldo6_resources[] = {
{0x15, 0x15, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo7_resources[] __devinitdata = {
+static struct resource ldo7_resources[] = {
{0x16, 0x16, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo8_resources[] __devinitdata = {
+static struct resource ldo8_resources[] = {
{0x17, 0x17, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo9_resources[] __devinitdata = {
+static struct resource ldo9_resources[] = {
{0x18, 0x18, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo10_resources[] __devinitdata = {
+static struct resource ldo10_resources[] = {
{0x19, 0x19, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo12_resources[] __devinitdata = {
+static struct resource ldo12_resources[] = {
{0x1a, 0x1a, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo_vibrator_resources[] __devinitdata = {
+static struct resource ldo_vibrator_resources[] = {
{0x28, 0x28, "ldo set", IORESOURCE_REG, },
};
-static struct resource ldo14_resources[] __devinitdata = {
+static struct resource ldo14_resources[] = {
{0x1b, 0x1b, "ldo set", IORESOURCE_REG, },
};
-static struct resource touch_resources[] __devinitdata = {
+static struct resource touch_resources[] = {
{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
};
-static struct resource onkey_resources[] __devinitdata = {
+static struct resource onkey_resources[] = {
{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
};
-static struct resource codec_resources[] __devinitdata = {
+static struct resource codec_resources[] = {
/* Headset microphone insertion or removal */
{PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,},
/* Hook-switch press or release */
@@ -143,12 +143,12 @@ static struct resource codec_resources[] __devinitdata = {
{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
};
-static struct resource battery_resources[] __devinitdata = {
+static struct resource battery_resources[] = {
{PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,},
{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,},
};
-static struct resource charger_resources[] __devinitdata = {
+static struct resource charger_resources[] = {
{PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAIL, PM8607_IRQ_CHG_FAIL, "charging timeout", IORESOURCE_IRQ,},
@@ -158,11 +158,11 @@ static struct resource charger_resources[] __devinitdata = {
{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
};
-static struct resource rtc_resources[] __devinitdata = {
+static struct resource rtc_resources[] = {
{PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
};
-static struct mfd_cell bk_devs[] __devinitdata = {
+static struct mfd_cell bk_devs[] = {
{
.name = "88pm860x-backlight",
.id = 0,
@@ -181,7 +181,7 @@ static struct mfd_cell bk_devs[] __devinitdata = {
},
};
-static struct mfd_cell led_devs[] __devinitdata = {
+static struct mfd_cell led_devs[] = {
{
.name = "88pm860x-led",
.id = 0,
@@ -215,7 +215,7 @@ static struct mfd_cell led_devs[] __devinitdata = {
},
};
-static struct mfd_cell reg_devs[] __devinitdata = {
+static struct mfd_cell reg_devs[] = {
{
.name = "88pm860x-regulator",
.id = 0,
@@ -565,7 +565,7 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
.xlate = irq_domain_xlate_onetwocell,
};
-static int __devinit device_irq_init(struct pm860x_chip *chip,
+static int device_irq_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
@@ -730,7 +730,7 @@ out:
}
EXPORT_SYMBOL(pm8606_osc_disable);
-static void __devinit device_osc_init(struct i2c_client *i2c)
+static void device_osc_init(struct i2c_client *i2c)
{
struct pm860x_chip *chip = i2c_get_clientdata(i2c);
@@ -745,7 +745,7 @@ static void __devinit device_osc_init(struct i2c_client *i2c)
chip->osc_status = PM8606_REF_GP_OSC_OFF;
}
-static void __devinit device_bk_init(struct pm860x_chip *chip,
+static void device_bk_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret, i;
@@ -765,7 +765,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add backlight subdev\n");
}
-static void __devinit device_led_init(struct pm860x_chip *chip,
+static void device_led_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret, i;
@@ -787,7 +787,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
}
}
-static void __devinit device_regulator_init(struct pm860x_chip *chip,
+static void device_regulator_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -866,7 +866,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
}
}
-static void __devinit device_rtc_init(struct pm860x_chip *chip,
+static void device_rtc_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -885,7 +885,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add rtc subdev\n");
}
-static void __devinit device_touch_init(struct pm860x_chip *chip,
+static void device_touch_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -904,7 +904,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add touch subdev\n");
}
-static void __devinit device_power_init(struct pm860x_chip *chip,
+static void device_power_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -951,7 +951,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
}
}
-static void __devinit device_onkey_init(struct pm860x_chip *chip,
+static void device_onkey_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -965,7 +965,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add onkey subdev\n");
}
-static void __devinit device_codec_init(struct pm860x_chip *chip,
+static void device_codec_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
int ret;
@@ -979,7 +979,7 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,
dev_err(chip->dev, "Failed to add codec subdev\n");
}
-static void __devinit device_8607_init(struct pm860x_chip *chip,
+static void device_8607_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
@@ -1040,7 +1040,7 @@ out:
return;
}
-static void __devinit device_8606_init(struct pm860x_chip *chip,
+static void device_8606_init(struct pm860x_chip *chip,
struct i2c_client *i2c,
struct pm860x_platform_data *pdata)
{
@@ -1049,7 +1049,7 @@ static void __devinit device_8606_init(struct pm860x_chip *chip,
device_led_init(chip, pdata);
}
-static int __devinit pm860x_device_init(struct pm860x_chip *chip,
+static int pm860x_device_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
chip->core_irq = 0;
@@ -1077,7 +1077,7 @@ static int __devinit pm860x_device_init(struct pm860x_chip *chip,
return 0;
}
-static void __devexit pm860x_device_exit(struct pm860x_chip *chip)
+static void pm860x_device_exit(struct pm860x_chip *chip)
{
device_irq_exit(chip);
mfd_remove_devices(chip->dev);
@@ -1109,7 +1109,7 @@ static struct regmap_config pm860x_regmap_config = {
.val_bits = 8,
};
-static int __devinit pm860x_dt_init(struct device_node *np,
+static int pm860x_dt_init(struct device_node *np,
struct device *dev,
struct pm860x_platform_data *pdata)
{
@@ -1127,7 +1127,7 @@ static int __devinit pm860x_dt_init(struct device_node *np,
return 0;
}
-static int __devinit pm860x_probe(struct i2c_client *client,
+static int pm860x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pm860x_platform_data *pdata = client->dev.platform_data;
@@ -1200,7 +1200,7 @@ err:
return ret;
}
-static int __devexit pm860x_remove(struct i2c_client *client)
+static int pm860x_remove(struct i2c_client *client)
{
struct pm860x_chip *chip = i2c_get_clientdata(client);
@@ -1258,7 +1258,7 @@ static struct i2c_driver pm860x_driver = {
.of_match_table = of_match_ptr(pm860x_dt_ids),
},
.probe = pm860x_probe,
- .remove = __devexit_p(pm860x_remove),
+ .remove = pm860x_remove,
.id_table = pm860x_id_table,
};
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index acab3ef8a310..2c10938b3567 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -63,6 +63,16 @@ config MFD_SM501_GPIO
lines on the SM501. The platform data is used to supply the
base number for the first GPIO line to register.
+config MFD_RTSX_PCI
+ tristate "Support for Realtek PCI-E card reader"
+ depends on PCI
+ select MFD_CORE
+ help
+ This supports for Realtek PCI-Express card reader including rts5209,
+ rts5229, rtl8411, etc. Realtek card reader supports access to many
+ types of memory cards, such as Memory Stick, Memory Stick Pro,
+ Secure Digital and MultiMediaCard.
+
config MFD_ASIC3
bool "Support for Compaq ASIC3"
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d8ccb630ddb0..b53db06d1b46 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -9,6 +9,9 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
+rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o
+obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
+
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 2b3dde571a50..2ec7725f4a08 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -661,8 +661,7 @@ struct ab3100_init_setting {
u8 setting;
};
-static const struct ab3100_init_setting __devinitconst
-ab3100_init_settings[] = {
+static const struct ab3100_init_setting ab3100_init_settings[] = {
{
.abreg = AB3100_MCA,
.setting = 0x01
@@ -708,7 +707,7 @@ ab3100_init_settings[] = {
},
};
-static int __devinit ab3100_setup(struct ab3100 *ab3100)
+static int ab3100_setup(struct ab3100 *ab3100)
{
int err = 0;
int i;
@@ -803,7 +802,7 @@ struct ab_family_id {
char *name;
};
-static const struct ab_family_id ids[] __devinitconst = {
+static const struct ab_family_id ids[] = {
/* AB3100 */
{
.id = 0xc0,
@@ -857,7 +856,7 @@ static const struct ab_family_id ids[] __devinitconst = {
},
};
-static int __devinit ab3100_probe(struct i2c_client *client,
+static int ab3100_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ab3100 *ab3100;
@@ -962,7 +961,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,
return err;
}
-static int __devexit ab3100_remove(struct i2c_client *client)
+static int ab3100_remove(struct i2c_client *client)
{
struct ab3100 *ab3100 = i2c_get_clientdata(client);
@@ -986,7 +985,7 @@ static struct i2c_driver ab3100_driver = {
},
.id_table = ab3100_id,
.probe = ab3100_probe,
- .remove = __devexit_p(ab3100_remove),
+ .remove = ab3100_remove,
};
static int __init ab3100_i2c_init(void)
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index 1667c77b5cde..127b00aadae3 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -623,7 +623,7 @@ static struct resource __devinitdata ab9540_gpio_resources[] = {
}
};
-static struct resource __devinitdata ab8500_gpadc_resources[] = {
+static struct resource ab8500_gpadc_resources[] = {
{
.name = "HW_CONV_END",
.start = AB8500_INT_GP_HW_ADC_CONV_END,
@@ -638,7 +638,7 @@ static struct resource __devinitdata ab8500_gpadc_resources[] = {
},
};
-static struct resource __devinitdata ab8500_rtc_resources[] = {
+static struct resource ab8500_rtc_resources[] = {
{
.name = "60S",
.start = AB8500_INT_RTC_60S,
@@ -653,7 +653,7 @@ static struct resource __devinitdata ab8500_rtc_resources[] = {
},
};
-static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
+static struct resource ab8500_poweronkey_db_resources[] = {
{
.name = "ONKEY_DBF",
.start = AB8500_INT_PON_KEY1DB_F,
@@ -668,7 +668,7 @@ static struct resource __devinitdata ab8500_poweronkey_db_resources[] = {
},
};
-static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
+static struct resource ab8500_av_acc_detect_resources[] = {
{
.name = "ACC_DETECT_1DB_F",
.start = AB8500_INT_ACC_DETECT_1DB_F,
@@ -707,7 +707,7 @@ static struct resource __devinitdata ab8500_av_acc_detect_resources[] = {
},
};
-static struct resource __devinitdata ab8500_charger_resources[] = {
+static struct resource ab8500_charger_resources[] = {
{
.name = "MAIN_CH_UNPLUG_DET",
.start = AB8500_INT_MAIN_CH_UNPLUG_DET,
@@ -788,7 +788,7 @@ static struct resource __devinitdata ab8500_charger_resources[] = {
},
};
-static struct resource __devinitdata ab8500_btemp_resources[] = {
+static struct resource ab8500_btemp_resources[] = {
{
.name = "BAT_CTRL_INDB",
.start = AB8500_INT_BAT_CTRL_INDB,
@@ -821,7 +821,7 @@ static struct resource __devinitdata ab8500_btemp_resources[] = {
},
};
-static struct resource __devinitdata ab8500_fg_resources[] = {
+static struct resource ab8500_fg_resources[] = {
{
.name = "NCONV_ACCU",
.start = AB8500_INT_CCN_CONV_ACC,
@@ -860,10 +860,10 @@ static struct resource __devinitdata ab8500_fg_resources[] = {
},
};
-static struct resource __devinitdata ab8500_chargalg_resources[] = {};
+static struct resource ab8500_chargalg_resources[] = {};
#ifdef CONFIG_DEBUG_FS
-static struct resource __devinitdata ab8500_debug_resources[] = {
+static struct resource ab8500_debug_resources[] = {
{
.name = "IRQ_FIRST",
.start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
@@ -879,7 +879,7 @@ static struct resource __devinitdata ab8500_debug_resources[] = {
};
#endif
-static struct resource __devinitdata ab8500_usb_resources[] = {
+static struct resource ab8500_usb_resources[] = {
{
.name = "ID_WAKEUP_R",
.start = AB8500_INT_ID_WAKEUP_R,
@@ -924,7 +924,7 @@ static struct resource __devinitdata ab8500_usb_resources[] = {
},
};
-static struct resource __devinitdata ab8505_iddet_resources[] = {
+static struct resource ab8505_iddet_resources[] = {
{
.name = "KeyDeglitch",
.start = AB8505_INT_KEYDEGLITCH,
@@ -957,7 +957,7 @@ static struct resource __devinitdata ab8505_iddet_resources[] = {
},
};
-static struct resource __devinitdata ab8500_temp_resources[] = {
+static struct resource ab8500_temp_resources[] = {
{
.name = "AB8500_TEMP_WARM",
.start = AB8500_INT_TEMP_WARM,
@@ -966,7 +966,7 @@ static struct resource __devinitdata ab8500_temp_resources[] = {
},
};
-static struct mfd_cell __devinitdata abx500_common_devs[] = {
+static struct mfd_cell abx500_common_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
@@ -1038,7 +1038,7 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = {
},
};
-static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
+static struct mfd_cell ab8500_bm_devs[] = {
{
.name = "ab8500-charger",
.num_resources = ARRAY_SIZE(ab8500_charger_resources),
@@ -1061,7 +1061,7 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = {
},
};
-static struct mfd_cell __devinitdata ab8500_devs[] = {
+static struct mfd_cell ab8500_devs[] = {
{
.name = "ab8500-gpio",
.of_compatible = "stericsson,ab8500-gpio",
@@ -1080,7 +1080,7 @@ static struct mfd_cell __devinitdata ab8500_devs[] = {
},
};
-static struct mfd_cell __devinitdata ab9540_devs[] = {
+static struct mfd_cell ab9540_devs[] = {
{
.name = "ab8500-gpio",
.num_resources = ARRAY_SIZE(ab9540_gpio_resources),
@@ -1097,7 +1097,7 @@ static struct mfd_cell __devinitdata ab9540_devs[] = {
};
/* Device list common to ab9540 and ab8505 */
-static struct mfd_cell __devinitdata ab9540_ab8505_devs[] = {
+static struct mfd_cell ab9540_ab8505_devs[] = {
{
.name = "ab-iddet",
.num_resources = ARRAY_SIZE(ab8505_iddet_resources),
@@ -1248,7 +1248,7 @@ static struct attribute_group ab9540_attr_group = {
.attrs = ab9540_sysfs_entries,
};
-static int __devinit ab8500_probe(struct platform_device *pdev)
+static int ab8500_probe(struct platform_device *pdev)
{
static char *switch_off_status[] = {
"Swoff bit programming",
@@ -1473,7 +1473,7 @@ out_free_ab8500:
return ret;
}
-static int __devexit ab8500_remove(struct platform_device *pdev)
+static int ab8500_remove(struct platform_device *pdev)
{
struct ab8500 *ab8500 = platform_get_drvdata(pdev);
@@ -1506,7 +1506,7 @@ static struct platform_driver ab8500_core_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_probe,
- .remove = __devexit_p(ab8500_remove),
+ .remove = ab8500_remove,
.id_table = ab8500_id,
};
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index c4cb806978ac..5a8e707bc038 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -552,7 +552,7 @@ static struct dentry *ab8500_bank_file;
static struct dentry *ab8500_address_file;
static struct dentry *ab8500_val_file;
-static int __devinit ab8500_debug_probe(struct platform_device *plf)
+static int ab8500_debug_probe(struct platform_device *plf)
{
debug_bank = AB8500_MISC;
debug_address = AB8500_REV_REG & 0x00FF;
@@ -597,7 +597,7 @@ exit_no_debugfs:
return -ENOMEM;
}
-static int __devexit ab8500_debug_remove(struct platform_device *plf)
+static int ab8500_debug_remove(struct platform_device *plf)
{
debugfs_remove(ab8500_val_file);
debugfs_remove(ab8500_address_file);
@@ -614,7 +614,7 @@ static struct platform_driver ab8500_debug_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_debug_probe,
- .remove = __devexit_p(ab8500_debug_remove)
+ .remove = ab8500_debug_remove
};
static int __init ab8500_debug_init(void)
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 29d72a259c85..3fb1f40d6389 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -571,7 +571,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
gpadc->cal_data[ADC_INPUT_VBAT].offset);
}
-static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
+static int ab8500_gpadc_probe(struct platform_device *pdev)
{
int ret = 0;
struct ab8500_gpadc *gpadc;
@@ -634,7 +634,7 @@ fail:
return ret;
}
-static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
+static int ab8500_gpadc_remove(struct platform_device *pdev)
{
struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
@@ -651,7 +651,7 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
- .remove = __devexit_p(ab8500_gpadc_remove),
+ .remove = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index c28d4eb1eff0..8a33b2c7eead 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -49,13 +49,13 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
(u8)(reg & 0xFF), mask, value);
}
-static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
+static int ab8500_sysctrl_probe(struct platform_device *pdev)
{
sysctrl_dev = &pdev->dev;
return 0;
}
-static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
+static int ab8500_sysctrl_remove(struct platform_device *pdev)
{
sysctrl_dev = NULL;
return 0;
@@ -67,7 +67,7 @@ static struct platform_driver ab8500_sysctrl_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_sysctrl_probe,
- .remove = __devexit_p(ab8500_sysctrl_remove),
+ .remove = ab8500_sysctrl_remove,
};
static int __init ab8500_sysctrl_init(void)
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index ea8b9475731d..210dd038bb5a 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -203,7 +203,7 @@ static int adp5520_remove_subdevs(struct adp5520_chip *chip)
return device_for_each_child(chip->dev, NULL, __remove_subdev);
}
-static int __devinit adp5520_probe(struct i2c_client *client,
+static int adp5520_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adp5520_platform_data *pdata = client->dev.platform_data;
@@ -307,7 +307,7 @@ out_free_chip:
return ret;
}
-static int __devexit adp5520_remove(struct i2c_client *client)
+static int adp5520_remove(struct i2c_client *client)
{
struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
@@ -356,7 +356,7 @@ static struct i2c_driver adp5520_driver = {
.pm = &adp5520_pm,
},
.probe = adp5520_probe,
- .remove = __devexit_p(adp5520_remove),
+ .remove = adp5520_remove,
.id_table = adp5520_id,
};
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 1b48f2094806..1a6f943f7337 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -98,9 +98,9 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
dev_err(arizona->dev, "AIF3 underclocked\n");
- if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
- dev_err(arizona->dev, "AIF3 underclocked\n");
if (val & ARIZONA_AIF2_UNDERCLOCKED_STS)
+ dev_err(arizona->dev, "AIF2 underclocked\n");
+ if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
dev_err(arizona->dev, "AIF1 underclocked\n");
if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 underclocked\n");
@@ -285,7 +285,7 @@ static struct mfd_cell wm5110_devs[] = {
{ .name = "wm5110-codec" },
};
-int __devinit arizona_dev_init(struct arizona *arizona)
+int arizona_dev_init(struct arizona *arizona)
{
struct device *dev = arizona->dev;
const char *type_name;
@@ -415,11 +415,19 @@ int __devinit arizona_dev_init(struct arizona *arizona)
/* If we have a /RESET GPIO we'll already be reset */
if (!arizona->pdata.reset) {
+ regcache_mark_dirty(arizona->regmap);
+
ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
if (ret != 0) {
dev_err(dev, "Failed to reset device: %d\n", ret);
goto err_reset;
}
+
+ ret = regcache_sync(arizona->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to sync device: %d\n", ret);
+ goto err_reset;
+ }
}
ret = arizona_wait_for_boot(arizona);
@@ -520,7 +528,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
break;
case WM5110:
ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
- ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
+ ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
break;
}
@@ -553,7 +561,7 @@ err_early:
}
EXPORT_SYMBOL_GPL(arizona_dev_init);
-int __devexit arizona_dev_exit(struct arizona *arizona)
+int arizona_dev_exit(struct arizona *arizona)
{
mfd_remove_devices(arizona->dev);
arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 570c4b438086..44a1bb969841 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -22,7 +22,7 @@
#include "arizona.h"
-static __devinit int arizona_i2c_probe(struct i2c_client *i2c,
+static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct arizona *arizona;
@@ -65,7 +65,7 @@ static __devinit int arizona_i2c_probe(struct i2c_client *i2c,
return arizona_dev_init(arizona);
}
-static int __devexit arizona_i2c_remove(struct i2c_client *i2c)
+static int arizona_i2c_remove(struct i2c_client *i2c)
{
struct arizona *arizona = dev_get_drvdata(&i2c->dev);
arizona_dev_exit(arizona);
@@ -86,7 +86,7 @@ static struct i2c_driver arizona_i2c_driver = {
.pm = &arizona_pm_ops,
},
.probe = arizona_i2c_probe,
- .remove = __devexit_p(arizona_i2c_remove),
+ .remove = arizona_i2c_remove,
.id_table = arizona_i2c_id,
};
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index ef0f2d001df2..b1b009177405 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -178,6 +178,7 @@ int arizona_irq_init(struct arizona *arizona)
switch (arizona->rev) {
case 0:
+ case 1:
ctrlif_error = false;
break;
default:
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index df2e5a8bee28..1b9fdd698b03 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -22,7 +22,7 @@
#include "arizona.h"
-static int __devinit arizona_spi_probe(struct spi_device *spi)
+static int arizona_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona;
@@ -65,7 +65,7 @@ static int __devinit arizona_spi_probe(struct spi_device *spi)
return arizona_dev_init(arizona);
}
-static int __devexit arizona_spi_remove(struct spi_device *spi)
+static int arizona_spi_remove(struct spi_device *spi)
{
struct arizona *arizona = dev_get_drvdata(&spi->dev);
arizona_dev_exit(arizona);
@@ -86,7 +86,7 @@ static struct spi_driver arizona_spi_driver = {
.pm = &arizona_pm_ops,
},
.probe = arizona_spi_probe,
- .remove = __devexit_p(arizona_spi_remove),
+ .remove = arizona_spi_remove,
.id_table = arizona_spi_ids,
};
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 62f0883a7630..1b15986c01e1 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -1039,7 +1039,7 @@ static int __init asic3_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit asic3_remove(struct platform_device *pdev)
+static int asic3_remove(struct platform_device *pdev)
{
int ret;
struct asic3 *asic = platform_get_drvdata(pdev);
@@ -1071,7 +1071,7 @@ static struct platform_driver asic3_device_driver = {
.driver = {
.name = "asic3",
},
- .remove = __devexit_p(asic3_remove),
+ .remove = asic3_remove,
.shutdown = asic3_shutdown,
};
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 2b282133c725..2e4752a9220a 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -71,9 +71,9 @@ static int cs5535_mfd_res_disable(struct platform_device *pdev)
return 0;
}
-static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
+static struct resource cs5535_mfd_resources[NR_BARS];
-static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
+static struct mfd_cell cs5535_mfd_cells[] = {
{
.id = SMB_BAR,
.name = "cs5535-smb",
@@ -113,7 +113,7 @@ static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
};
#ifdef CONFIG_OLPC
-static void __devinit cs5535_clone_olpc_cells(void)
+static void cs5535_clone_olpc_cells(void)
{
const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
@@ -126,7 +126,7 @@ static void __devinit cs5535_clone_olpc_cells(void)
static void cs5535_clone_olpc_cells(void) { }
#endif
-static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
+static int cs5535_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int err, i;
@@ -166,7 +166,7 @@ err_disable:
return err;
}
-static void __devexit cs5535_mfd_remove(struct pci_dev *pdev)
+static void cs5535_mfd_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
pci_disable_device(pdev);
@@ -183,7 +183,7 @@ static struct pci_driver cs5535_mfd_driver = {
.name = DRV_NAME,
.id_table = cs5535_mfd_pci_tbl,
.probe = cs5535_mfd_probe,
- .remove = __devexit_p(cs5535_mfd_remove),
+ .remove = cs5535_mfd_remove,
};
module_pci_driver(cs5535_mfd_driver);
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 1924b857a0fb..05176cd2862b 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -246,7 +246,7 @@ int da903x_query_status(struct device *dev, unsigned int sbits)
}
EXPORT_SYMBOL(da903x_query_status);
-static int __devinit da9030_init_chip(struct da903x_chip *chip)
+static int da9030_init_chip(struct da903x_chip *chip)
{
uint8_t chip_id;
int err;
@@ -459,7 +459,7 @@ static int da903x_remove_subdevs(struct da903x_chip *chip)
return device_for_each_child(chip->dev, NULL, __remove_subdev);
}
-static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
+static int da903x_add_subdevs(struct da903x_chip *chip,
struct da903x_platform_data *pdata)
{
struct da903x_subdev_info *subdev;
@@ -491,7 +491,7 @@ failed:
return ret;
}
-static int __devinit da903x_probe(struct i2c_client *client,
+static int da903x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct da903x_platform_data *pdata = client->dev.platform_data;
@@ -544,7 +544,7 @@ out_free_chip:
return ret;
}
-static int __devexit da903x_remove(struct i2c_client *client)
+static int da903x_remove(struct i2c_client *client)
{
struct da903x_chip *chip = i2c_get_clientdata(client);
@@ -560,7 +560,7 @@ static struct i2c_driver da903x_driver = {
.owner = THIS_MODULE,
},
.probe = da903x_probe,
- .remove = __devexit_p(da903x_remove),
+ .remove = da903x_remove,
.id_table = da903x_id_table,
};
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index a0a62b24621b..689b747416af 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -515,7 +515,7 @@ static struct resource da9052_tsi_resources[] = {
},
};
-static struct mfd_cell __devinitdata da9052_subdev_info[] = {
+static struct mfd_cell da9052_subdev_info[] = {
{
.name = "da9052-regulator",
.id = 1,
@@ -769,7 +769,7 @@ struct regmap_config da9052_regmap_config = {
};
EXPORT_SYMBOL_GPL(da9052_regmap_config);
-int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
+int da9052_device_init(struct da9052 *da9052, u8 chip_id)
{
struct da9052_pdata *pdata = da9052->dev->platform_data;
int ret;
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 352c58b5a90d..ac74a4d1daea 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -64,7 +64,7 @@ static const struct of_device_id dialog_dt_ids[] = {
};
#endif
-static int __devinit da9052_i2c_probe(struct i2c_client *client,
+static int da9052_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct da9052 *da9052;
@@ -121,7 +121,7 @@ static int __devinit da9052_i2c_probe(struct i2c_client *client,
return 0;
}
-static int __devexit da9052_i2c_remove(struct i2c_client *client)
+static int da9052_i2c_remove(struct i2c_client *client)
{
struct da9052 *da9052 = i2c_get_clientdata(client);
@@ -131,7 +131,7 @@ static int __devexit da9052_i2c_remove(struct i2c_client *client)
static struct i2c_driver da9052_i2c_driver = {
.probe = da9052_i2c_probe,
- .remove = __devexit_p(da9052_i2c_remove),
+ .remove = da9052_i2c_remove,
.id_table = da9052_i2c_id,
.driver = {
.name = "da9052",
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
index dbeadc5a6436..61d63b93576c 100644
--- a/drivers/mfd/da9052-spi.c
+++ b/drivers/mfd/da9052-spi.c
@@ -21,7 +21,7 @@
#include <linux/mfd/da9052/da9052.h>
-static int __devinit da9052_spi_probe(struct spi_device *spi)
+static int da9052_spi_probe(struct spi_device *spi)
{
int ret;
const struct spi_device_id *id = spi_get_device_id(spi);
@@ -58,7 +58,7 @@ static int __devinit da9052_spi_probe(struct spi_device *spi)
return 0;
}
-static int __devexit da9052_spi_remove(struct spi_device *spi)
+static int da9052_spi_remove(struct spi_device *spi)
{
struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
@@ -76,7 +76,7 @@ static struct spi_device_id da9052_spi_id[] = {
static struct spi_driver da9052_spi_driver = {
.probe = da9052_spi_probe,
- .remove = __devexit_p(da9052_spi_remove),
+ .remove = da9052_spi_remove,
.id_table = da9052_spi_id,
.driver = {
.name = "da9052",
diff --git a/drivers/mfd/da9055-core.c b/drivers/mfd/da9055-core.c
index ff6c77f392bd..f56a1a9f7777 100644
--- a/drivers/mfd/da9055-core.c
+++ b/drivers/mfd/da9055-core.c
@@ -377,7 +377,7 @@ static struct regmap_irq_chip da9055_regmap_irq_chip = {
.num_irqs = ARRAY_SIZE(da9055_irqs),
};
-int __devinit da9055_device_init(struct da9055 *da9055)
+int da9055_device_init(struct da9055 *da9055)
{
struct da9055_pdata *pdata = da9055->dev->platform_data;
int ret;
@@ -412,7 +412,7 @@ err:
return ret;
}
-void __devexit da9055_device_exit(struct da9055 *da9055)
+void da9055_device_exit(struct da9055 *da9055)
{
regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
mfd_remove_devices(da9055->dev);
diff --git a/drivers/mfd/da9055-i2c.c b/drivers/mfd/da9055-i2c.c
index 88f6dca53bac..607387ffe8ca 100644
--- a/drivers/mfd/da9055-i2c.c
+++ b/drivers/mfd/da9055-i2c.c
@@ -18,7 +18,7 @@
#include <linux/mfd/da9055/core.h>
-static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
+static int da9055_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct da9055 *da9055;
@@ -44,7 +44,7 @@ static int __devinit da9055_i2c_probe(struct i2c_client *i2c,
return da9055_device_init(da9055);
}
-static int __devexit da9055_i2c_remove(struct i2c_client *i2c)
+static int da9055_i2c_remove(struct i2c_client *i2c)
{
struct da9055 *da9055 = i2c_get_clientdata(i2c);
@@ -60,7 +60,7 @@ static struct i2c_device_id da9055_i2c_id[] = {
static struct i2c_driver da9055_i2c_driver = {
.probe = da9055_i2c_probe,
- .remove = __devexit_p(da9055_i2c_remove),
+ .remove = da9055_i2c_remove,
.id_table = da9055_i2c_id,
.driver = {
.name = "da9055",
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
index 45e83a68641b..c0bcc872af4e 100644
--- a/drivers/mfd/davinci_voicecodec.c
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -151,7 +151,7 @@ fail1:
return ret;
}
-static int __devexit davinci_vc_remove(struct platform_device *pdev)
+static int davinci_vc_remove(struct platform_device *pdev)
{
struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
@@ -174,7 +174,7 @@ static struct platform_driver davinci_vc_driver = {
.name = "davinci_voicecodec",
.owner = THIS_MODULE,
},
- .remove = __devexit_p(davinci_vc_remove),
+ .remove = davinci_vc_remove,
};
static int __init davinci_vc_init(void)
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 00b8b0f3dfb6..dc5691569370 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -31,6 +31,7 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/db8500-prcmu.h>
#include <linux/regulator/machine.h>
+#include <linux/cpufreq.h>
#include <asm/hardware/gic.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -420,9 +421,6 @@ static struct {
static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
-/* Functions definition */
-static void compute_armss_rate(void);
-
/* Spinlocks */
static DEFINE_SPINLOCK(prcmu_lock);
static DEFINE_SPINLOCK(clkout_lock);
@@ -1019,7 +1017,6 @@ int db8500_prcmu_set_arm_opp(u8 opp)
(mb1_transfer.ack.arm_opp != opp))
r = -EIO;
- compute_armss_rate();
mutex_unlock(&mb1_transfer.lock);
return r;
@@ -1169,12 +1166,12 @@ int db8500_prcmu_get_ape_opp(void)
}
/**
- * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
+ * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
* @enable: true to request the higher voltage, false to drop a request.
*
* Calls to this function to enable and disable requests must be balanced.
*/
-int prcmu_request_ape_opp_100_voltage(bool enable)
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
{
int r = 0;
u8 header;
@@ -1669,13 +1666,8 @@ static unsigned long clock_rate(u8 clock)
else
return 0;
}
-static unsigned long latest_armss_rate;
-static unsigned long armss_rate(void)
-{
- return latest_armss_rate;
-}
-static void compute_armss_rate(void)
+static unsigned long armss_rate(void)
{
u32 r;
unsigned long rate;
@@ -1700,7 +1692,7 @@ static void compute_armss_rate(void)
rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
}
- latest_armss_rate = rate;
+ return rate;
}
static unsigned long dsiclk_rate(u8 n)
@@ -1820,6 +1812,35 @@ static long round_clock_rate(u8 clock, unsigned long rate)
return rounded_rate;
}
+/* CPU FREQ table, may be changed due to if MAX_OPP is supported. */
+static struct cpufreq_frequency_table db8500_cpufreq_table[] = {
+ { .frequency = 200000, .index = ARM_EXTCLK,},
+ { .frequency = 400000, .index = ARM_50_OPP,},
+ { .frequency = 800000, .index = ARM_100_OPP,},
+ { .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */
+ { .frequency = CPUFREQ_TABLE_END,},
+};
+
+static long round_armss_rate(unsigned long rate)
+{
+ long freq = 0;
+ int i = 0;
+
+ /* cpufreq table frequencies is in KHz. */
+ rate = rate / 1000;
+
+ /* Find the corresponding arm opp from the cpufreq table. */
+ while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+ freq = db8500_cpufreq_table[i].frequency;
+ if (freq == rate)
+ break;
+ i++;
+ }
+
+ /* Return the last valid value, even if a match was not found. */
+ return freq * 1000;
+}
+
#define MIN_PLL_VCO_RATE 600000000ULL
#define MAX_PLL_VCO_RATE 1680640000ULL
@@ -1891,6 +1912,8 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate)
{
if (clock < PRCMU_NUM_REG_CLOCKS)
return round_clock_rate(clock, rate);
+ else if (clock == PRCMU_ARMSS)
+ return round_armss_rate(rate);
else if (clock == PRCMU_PLLDSI)
return round_plldsi_rate(rate);
else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -1950,6 +1973,27 @@ static void set_clock_rate(u8 clock, unsigned long rate)
spin_unlock_irqrestore(&clk_mgt_lock, flags);
}
+static int set_armss_rate(unsigned long rate)
+{
+ int i = 0;
+
+ /* cpufreq table frequencies is in KHz. */
+ rate = rate / 1000;
+
+ /* Find the corresponding arm opp from the cpufreq table. */
+ while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+ if (db8500_cpufreq_table[i].frequency == rate)
+ break;
+ i++;
+ }
+
+ if (db8500_cpufreq_table[i].frequency != rate)
+ return -EINVAL;
+
+ /* Set the new arm opp. */
+ return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].index);
+}
+
static int set_plldsi_rate(unsigned long rate)
{
unsigned long src_rate;
@@ -2030,6 +2074,8 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate)
{
if (clock < PRCMU_NUM_REG_CLOCKS)
set_clock_rate(clock, rate);
+ else if (clock == PRCMU_ARMSS)
+ return set_armss_rate(rate);
else if (clock == PRCMU_PLLDSI)
return set_plldsi_rate(rate);
else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -2754,8 +2800,6 @@ void __init db8500_prcmu_early_init(void)
init_completion(&mb5_transfer.work);
INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
-
- compute_armss_rate();
}
static void __init init_prcm_registers(void)
@@ -3020,6 +3064,8 @@ static struct mfd_cell db8500_prcmu_devs[] = {
{
.name = "cpufreq-u8500",
.of_compatible = "stericsson,cpufreq-u8500",
+ .platform_data = &db8500_cpufreq_table,
+ .pdata_size = sizeof(db8500_cpufreq_table),
},
{
.name = "ab8500-core",
@@ -3030,11 +3076,19 @@ static struct mfd_cell db8500_prcmu_devs[] = {
},
};
+static void db8500_prcmu_update_cpufreq(void)
+{
+ if (prcmu_has_arm_maxopp()) {
+ db8500_cpufreq_table[3].frequency = 1000000;
+ db8500_cpufreq_table[3].index = ARM_MAX_OPP;
+ }
+}
+
/**
* prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
*
*/
-static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
+static int db8500_prcmu_probe(struct platform_device *pdev)
{
struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
@@ -3074,6 +3128,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
if (cpu_is_u8500v20_or_later())
prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+ db8500_prcmu_update_cpufreq();
+
err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);
if (err) {
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index db662e2dcfa5..b7a61f0f27a4 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -371,7 +371,7 @@ static int pcap_remove_subdev(struct device *dev, void *unused)
return 0;
}
-static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
+static int pcap_add_subdev(struct pcap_chip *pcap,
struct pcap_subdev *subdev)
{
struct platform_device *pdev;
@@ -391,7 +391,7 @@ static int __devinit pcap_add_subdev(struct pcap_chip *pcap,
return ret;
}
-static int __devexit ezx_pcap_remove(struct spi_device *spi)
+static int ezx_pcap_remove(struct spi_device *spi)
{
struct pcap_chip *pcap = dev_get_drvdata(&spi->dev);
struct pcap_platform_data *pdata = spi->dev.platform_data;
@@ -420,7 +420,7 @@ static int __devexit ezx_pcap_remove(struct spi_device *spi)
return 0;
}
-static int __devinit ezx_pcap_probe(struct spi_device *spi)
+static int ezx_pcap_probe(struct spi_device *spi)
{
struct pcap_platform_data *pdata = spi->dev.platform_data;
struct pcap_chip *pcap;
@@ -525,7 +525,7 @@ ret:
static struct spi_driver ezxpcap_driver = {
.probe = ezx_pcap_probe,
- .remove = __devexit_p(ezx_pcap_remove),
+ .remove = ezx_pcap_remove,
.driver = {
.name = "ezx-pcap",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index d55065cc324c..324187c0c124 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -327,7 +327,7 @@ static void htcpld_chip_reset(struct i2c_client *client)
client, (chip_data->cache_out = chip_data->reset));
}
-static int __devinit htcpld_setup_chip_irq(
+static int htcpld_setup_chip_irq(
struct platform_device *pdev,
int chip_index)
{
@@ -361,7 +361,7 @@ static int __devinit htcpld_setup_chip_irq(
return ret;
}
-static int __devinit htcpld_register_chip_i2c(
+static int htcpld_register_chip_i2c(
struct platform_device *pdev,
int chip_index)
{
@@ -419,7 +419,7 @@ static int __devinit htcpld_register_chip_i2c(
return 0;
}
-static void __devinit htcpld_unregister_chip_i2c(
+static void htcpld_unregister_chip_i2c(
struct platform_device *pdev,
int chip_index)
{
@@ -434,7 +434,7 @@ static void __devinit htcpld_unregister_chip_i2c(
i2c_unregister_device(chip->client);
}
-static int __devinit htcpld_register_chip_gpio(
+static int htcpld_register_chip_gpio(
struct platform_device *pdev,
int chip_index)
{
@@ -501,7 +501,7 @@ static int __devinit htcpld_register_chip_gpio(
return 0;
}
-static int __devinit htcpld_setup_chips(struct platform_device *pdev)
+static int htcpld_setup_chips(struct platform_device *pdev)
{
struct htcpld_data *htcpld;
struct device *dev = &pdev->dev;
@@ -563,7 +563,7 @@ static int __devinit htcpld_setup_chips(struct platform_device *pdev)
return 0;
}
-static int __devinit htcpld_core_probe(struct platform_device *pdev)
+static int htcpld_core_probe(struct platform_device *pdev)
{
struct htcpld_data *htcpld;
struct device *dev = &pdev->dev;
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
index 266bdc5bd96d..ab8d0b2739b2 100644
--- a/drivers/mfd/intel_msic.c
+++ b/drivers/mfd/intel_msic.c
@@ -306,7 +306,7 @@ int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
}
EXPORT_SYMBOL_GPL(intel_msic_irq_read);
-static int __devinit intel_msic_init_devices(struct intel_msic *msic)
+static int intel_msic_init_devices(struct intel_msic *msic)
{
struct platform_device *pdev = msic->pdev;
struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
@@ -364,7 +364,7 @@ fail:
return ret;
}
-static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
+static void intel_msic_remove_devices(struct intel_msic *msic)
{
struct platform_device *pdev = msic->pdev;
struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
@@ -375,7 +375,7 @@ static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
gpio_free(pdata->ocd->gpio);
}
-static int __devinit intel_msic_probe(struct platform_device *pdev)
+static int intel_msic_probe(struct platform_device *pdev)
{
struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
struct intel_msic *msic;
@@ -445,7 +445,7 @@ static int __devinit intel_msic_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit intel_msic_remove(struct platform_device *pdev)
+static int intel_msic_remove(struct platform_device *pdev)
{
struct intel_msic *msic = platform_get_drvdata(pdev);
@@ -457,7 +457,7 @@ static int __devexit intel_msic_remove(struct platform_device *pdev)
static struct platform_driver intel_msic_driver = {
.probe = intel_msic_probe,
- .remove = __devexit_p(intel_msic_remove),
+ .remove = intel_msic_remove,
.driver = {
.name = "intel_msic",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index 965c4801df8a..45ece11cc27c 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -63,7 +63,7 @@ struct cmodio_device {
* Subdevices using the mfd-core API
*/
-static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
+static int cmodio_setup_subdevice(struct cmodio_device *priv,
char *name, unsigned int devno,
unsigned int modno)
{
@@ -120,7 +120,7 @@ static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
}
/* Probe each submodule using kernel parameters */
-static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
+static int cmodio_probe_submodules(struct cmodio_device *priv)
{
struct pci_dev *pdev = priv->pdev;
unsigned int num_probed = 0;
@@ -177,7 +177,7 @@ static const struct attribute_group cmodio_sysfs_attr_group = {
* PCI Driver
*/
-static int __devinit cmodio_pci_probe(struct pci_dev *dev,
+static int cmodio_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct cmodio_device *priv;
@@ -254,7 +254,7 @@ out_return:
return ret;
}
-static void __devexit cmodio_pci_remove(struct pci_dev *dev)
+static void cmodio_pci_remove(struct pci_dev *dev)
{
struct cmodio_device *priv = pci_get_drvdata(dev);
@@ -280,7 +280,7 @@ static struct pci_driver cmodio_pci_driver = {
.name = DRV_NAME,
.id_table = cmodio_pci_ids,
.probe = cmodio_pci_probe,
- .remove = __devexit_p(cmodio_pci_remove),
+ .remove = cmodio_pci_remove,
};
module_pci_driver(cmodio_pci_driver);
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index c6b6d7dda517..0b8b55bb9b11 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -202,7 +202,7 @@ static struct mfd_cell jz4740_adc_cells[] = {
},
};
-static int __devinit jz4740_adc_probe(struct platform_device *pdev)
+static int jz4740_adc_probe(struct platform_device *pdev)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
@@ -307,7 +307,7 @@ err_free:
return ret;
}
-static int __devexit jz4740_adc_remove(struct platform_device *pdev)
+static int jz4740_adc_remove(struct platform_device *pdev)
{
struct jz4740_adc *adc = platform_get_drvdata(pdev);
@@ -332,7 +332,7 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
static struct platform_driver jz4740_adc_driver = {
.probe = jz4740_adc_probe,
- .remove = __devexit_p(jz4740_adc_remove),
+ .remove = jz4740_adc_remove,
.driver = {
.name = "jz4740-adc",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 24212f45b201..ceebf2c1ea97 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -382,7 +382,7 @@ static struct attribute_group lm3533_attribute_group = {
.attrs = lm3533_attributes
};
-static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
+static int lm3533_device_als_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
int ret;
@@ -405,7 +405,7 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
return 0;
}
-static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
+static int lm3533_device_bl_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
int i;
@@ -434,7 +434,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
return 0;
}
-static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
+static int lm3533_device_led_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
int i;
@@ -463,7 +463,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
return 0;
}
-static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
+static int lm3533_device_setup(struct lm3533 *lm3533,
struct lm3533_platform_data *pdata)
{
int ret;
@@ -479,7 +479,7 @@ static int __devinit lm3533_device_setup(struct lm3533 *lm3533,
return 0;
}
-static int __devinit lm3533_device_init(struct lm3533 *lm3533)
+static int lm3533_device_init(struct lm3533 *lm3533)
{
struct lm3533_platform_data *pdata = lm3533->dev->platform_data;
int ret;
@@ -534,7 +534,7 @@ err_disable:
return ret;
}
-static void __devexit lm3533_device_exit(struct lm3533 *lm3533)
+static void lm3533_device_exit(struct lm3533 *lm3533)
{
dev_dbg(lm3533->dev, "%s\n", __func__);
@@ -596,7 +596,7 @@ static struct regmap_config regmap_config = {
.precious_reg = lm3533_precious_register,
};
-static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
+static int lm3533_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct lm3533 *lm3533;
@@ -624,7 +624,7 @@ static int __devinit lm3533_i2c_probe(struct i2c_client *i2c,
return 0;
}
-static int __devexit lm3533_i2c_remove(struct i2c_client *i2c)
+static int lm3533_i2c_remove(struct i2c_client *i2c)
{
struct lm3533 *lm3533 = i2c_get_clientdata(i2c);
@@ -648,7 +648,7 @@ static struct i2c_driver lm3533_i2c_driver = {
},
.id_table = lm3533_i2c_ids,
.probe = lm3533_i2c_probe,
- .remove = __devexit_p(lm3533_i2c_remove),
+ .remove = lm3533_i2c_remove,
};
static int __init lm3533_i2c_init(void)
diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c
index 3e94a699833c..c3d3c9b4d3ad 100644
--- a/drivers/mfd/lp8788.c
+++ b/drivers/mfd/lp8788.c
@@ -203,7 +203,7 @@ static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id)
ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
}
-static int __devexit lp8788_remove(struct i2c_client *cl)
+static int lp8788_remove(struct i2c_client *cl)
{
struct lp8788 *lp = i2c_get_clientdata(cl);
@@ -224,7 +224,7 @@ static struct i2c_driver lp8788_driver = {
.owner = THIS_MODULE,
},
.probe = lp8788_probe,
- .remove = __devexit_p(lp8788_remove),
+ .remove = lp8788_remove,
.id_table = lp8788_ids,
};
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index a22544fe5319..2ad24caa07db 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -196,7 +196,7 @@ enum lpc_chipsets {
LPC_LPT_LP, /* Lynx Point-LP */
};
-struct lpc_ich_info lpc_chipset_info[] __devinitdata = {
+struct lpc_ich_info lpc_chipset_info[] = {
[LPC_ICH] = {
.name = "ICH",
.iTCO_version = 1,
@@ -672,7 +672,7 @@ static void lpc_ich_restore_config_space(struct pci_dev *dev)
}
}
-static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
+static void lpc_ich_enable_acpi_space(struct pci_dev *dev)
{
u8 reg_save;
@@ -681,7 +681,7 @@ static void __devinit lpc_ich_enable_acpi_space(struct pci_dev *dev)
lpc_ich_acpi_save = reg_save;
}
-static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
+static void lpc_ich_enable_gpio_space(struct pci_dev *dev)
{
u8 reg_save;
@@ -690,7 +690,7 @@ static void __devinit lpc_ich_enable_gpio_space(struct pci_dev *dev)
lpc_ich_gpio_save = reg_save;
}
-static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
+static void lpc_ich_finalize_cell(struct mfd_cell *cell,
const struct pci_device_id *id)
{
cell->platform_data = &lpc_chipset_info[id->driver_data];
@@ -702,7 +702,7 @@ static void __devinit lpc_ich_finalize_cell(struct mfd_cell *cell,
* GPIO groups and it's enough to have access to one of these to instantiate
* the device.
*/
-static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
+static int lpc_ich_check_conflict_gpio(struct resource *res)
{
int ret;
u8 use_gpio = 0;
@@ -721,7 +721,7 @@ static int __devinit lpc_ich_check_conflict_gpio(struct resource *res)
return use_gpio ? use_gpio : ret;
}
-static int __devinit lpc_ich_init_gpio(struct pci_dev *dev,
+static int lpc_ich_init_gpio(struct pci_dev *dev,
const struct pci_device_id *id)
{
u32 base_addr_cfg;
@@ -798,7 +798,7 @@ gpio_done:
return ret;
}
-static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
+static int lpc_ich_init_wdt(struct pci_dev *dev,
const struct pci_device_id *id)
{
u32 base_addr_cfg;
@@ -852,7 +852,7 @@ wdt_done:
return ret;
}
-static int __devinit lpc_ich_probe(struct pci_dev *dev,
+static int lpc_ich_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int ret;
@@ -878,7 +878,7 @@ static int __devinit lpc_ich_probe(struct pci_dev *dev,
return 0;
}
-static void __devexit lpc_ich_remove(struct pci_dev *dev)
+static void lpc_ich_remove(struct pci_dev *dev)
{
mfd_remove_devices(&dev->dev);
lpc_ich_restore_config_space(dev);
@@ -888,7 +888,7 @@ static struct pci_driver lpc_ich_driver = {
.name = "lpc_ich",
.id_table = lpc_ich_ids,
.probe = lpc_ich_probe,
- .remove = __devexit_p(lpc_ich_remove),
+ .remove = lpc_ich_remove,
};
static int __init lpc_ich_init(void)
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
index f6b9c5c96b24..5624fcbba69b 100644
--- a/drivers/mfd/lpc_sch.c
+++ b/drivers/mfd/lpc_sch.c
@@ -83,7 +83,7 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
};
MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
-static int __devinit lpc_sch_probe(struct pci_dev *dev,
+static int lpc_sch_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
unsigned int base_addr_cfg;
@@ -164,7 +164,7 @@ out_dev:
return ret;
}
-static void __devexit lpc_sch_remove(struct pci_dev *dev)
+static void lpc_sch_remove(struct pci_dev *dev)
{
mfd_remove_devices(&dev->dev);
}
@@ -173,7 +173,7 @@ static struct pci_driver lpc_sch_driver = {
.name = "lpc_sch",
.id_table = lpc_sch_ids,
.probe = lpc_sch_probe,
- .remove = __devexit_p(lpc_sch_remove),
+ .remove = lpc_sch_remove,
};
module_pci_driver(lpc_sch_driver);
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index d9e24c849a00..f6878f8db57d 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -45,7 +45,7 @@ static struct regmap_config max77686_regmap_config = {
};
#ifdef CONFIG_OF
-static struct of_device_id __devinitdata max77686_pmic_dt_match[] = {
+static struct of_device_id max77686_pmic_dt_match[] = {
{.compatible = "maxim,max77686", .data = 0},
{},
};
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 17f2593d82b8..e9b1c93a3ade 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -183,7 +183,7 @@ static void max8907_power_off(void)
MAX8907_MASK_POWER_OFF, MAX8907_MASK_POWER_OFF);
}
-static __devinit int max8907_i2c_probe(struct i2c_client *i2c,
+static int max8907_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max8907 *max8907;
@@ -288,7 +288,7 @@ err_alloc_drvdata:
return ret;
}
-static __devexit int max8907_i2c_remove(struct i2c_client *i2c)
+static int max8907_i2c_remove(struct i2c_client *i2c)
{
struct max8907 *max8907 = i2c_get_clientdata(i2c);
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index 9f54c04912f2..e32466e865b9 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -19,12 +19,12 @@
#include <linux/mfd/core.h>
#include <linux/mfd/max8925.h>
-static struct resource bk_resources[] __devinitdata = {
+static struct resource bk_resources[] = {
{ 0x84, 0x84, "mode control", IORESOURCE_REG, },
{ 0x85, 0x85, "control", IORESOURCE_REG, },
};
-static struct mfd_cell bk_devs[] __devinitdata = {
+static struct mfd_cell bk_devs[] = {
{
.name = "max8925-backlight",
.num_resources = ARRAY_SIZE(bk_resources),
@@ -110,99 +110,99 @@ static struct mfd_cell onkey_devs[] = {
},
};
-static struct resource sd1_resources[] __devinitdata = {
+static struct resource sd1_resources[] = {
{0x06, 0x06, "sdv", IORESOURCE_REG, },
};
-static struct resource sd2_resources[] __devinitdata = {
+static struct resource sd2_resources[] = {
{0x09, 0x09, "sdv", IORESOURCE_REG, },
};
-static struct resource sd3_resources[] __devinitdata = {
+static struct resource sd3_resources[] = {
{0x0c, 0x0c, "sdv", IORESOURCE_REG, },
};
-static struct resource ldo1_resources[] __devinitdata = {
+static struct resource ldo1_resources[] = {
{0x1a, 0x1a, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo2_resources[] __devinitdata = {
+static struct resource ldo2_resources[] = {
{0x1e, 0x1e, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo3_resources[] __devinitdata = {
+static struct resource ldo3_resources[] = {
{0x22, 0x22, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo4_resources[] __devinitdata = {
+static struct resource ldo4_resources[] = {
{0x26, 0x26, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo5_resources[] __devinitdata = {
+static struct resource ldo5_resources[] = {
{0x2a, 0x2a, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo6_resources[] __devinitdata = {
+static struct resource ldo6_resources[] = {
{0x2e, 0x2e, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo7_resources[] __devinitdata = {
+static struct resource ldo7_resources[] = {
{0x32, 0x32, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo8_resources[] __devinitdata = {
+static struct resource ldo8_resources[] = {
{0x36, 0x36, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo9_resources[] __devinitdata = {
+static struct resource ldo9_resources[] = {
{0x3a, 0x3a, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo10_resources[] __devinitdata = {
+static struct resource ldo10_resources[] = {
{0x3e, 0x3e, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo11_resources[] __devinitdata = {
+static struct resource ldo11_resources[] = {
{0x42, 0x42, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo12_resources[] __devinitdata = {
+static struct resource ldo12_resources[] = {
{0x46, 0x46, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo13_resources[] __devinitdata = {
+static struct resource ldo13_resources[] = {
{0x4a, 0x4a, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo14_resources[] __devinitdata = {
+static struct resource ldo14_resources[] = {
{0x4e, 0x4e, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo15_resources[] __devinitdata = {
+static struct resource ldo15_resources[] = {
{0x52, 0x52, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo16_resources[] __devinitdata = {
+static struct resource ldo16_resources[] = {
{0x12, 0x12, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo17_resources[] __devinitdata = {
+static struct resource ldo17_resources[] = {
{0x16, 0x16, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo18_resources[] __devinitdata = {
+static struct resource ldo18_resources[] = {
{0x74, 0x74, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo19_resources[] __devinitdata = {
+static struct resource ldo19_resources[] = {
{0x5e, 0x5e, "ldov", IORESOURCE_REG, },
};
-static struct resource ldo20_resources[] __devinitdata = {
+static struct resource ldo20_resources[] = {
{0x9e, 0x9e, "ldov", IORESOURCE_REG, },
};
-static struct mfd_cell reg_devs[] __devinitdata = {
+static struct mfd_cell reg_devs[] = {
{
.name = "max8925-regulator",
.id = 0,
@@ -714,7 +714,7 @@ tsc_irq:
return 0;
}
-static void __devinit init_regulator(struct max8925_chip *chip,
+static void init_regulator(struct max8925_chip *chip,
struct max8925_platform_data *pdata)
{
int ret;
@@ -821,7 +821,7 @@ static void __devinit init_regulator(struct max8925_chip *chip,
}
}
-int __devinit max8925_device_init(struct max8925_chip *chip,
+int max8925_device_init(struct max8925_chip *chip,
struct max8925_platform_data *pdata)
{
int ret;
@@ -901,7 +901,7 @@ out:
return ret;
}
-void __devexit max8925_device_exit(struct max8925_chip *chip)
+void max8925_device_exit(struct max8925_chip *chip)
{
if (chip->core_irq)
free_irq(chip->core_irq, chip);
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index d9e4b36edee9..00b5b456063d 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -135,7 +135,7 @@ static const struct i2c_device_id max8925_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, max8925_id_table);
-static int __devinit max8925_probe(struct i2c_client *client,
+static int max8925_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max8925_platform_data *pdata = client->dev.platform_data;
@@ -168,7 +168,7 @@ static int __devinit max8925_probe(struct i2c_client *client,
return 0;
}
-static int __devexit max8925_remove(struct i2c_client *client)
+static int max8925_remove(struct i2c_client *client)
{
struct max8925_chip *chip = i2c_get_clientdata(client);
@@ -210,7 +210,7 @@ static struct i2c_driver max8925_driver = {
.pm = &max8925_pm_ops,
},
.probe = max8925_probe,
- .remove = __devexit_p(max8925_remove),
+ .remove = max8925_remove,
.id_table = max8925_id_table,
};
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
index 9d18dde3cd2a..7957999f30bb 100644
--- a/drivers/mfd/mc13xxx-i2c.c
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -85,7 +85,7 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
return ret;
}
-static int __devexit mc13xxx_i2c_remove(struct i2c_client *client)
+static int mc13xxx_i2c_remove(struct i2c_client *client)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
@@ -102,7 +102,7 @@ static struct i2c_driver mc13xxx_i2c_driver = {
.of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_i2c_probe,
- .remove = __devexit_p(mc13xxx_i2c_remove),
+ .remove = mc13xxx_i2c_remove,
};
static int __init mc13xxx_i2c_init(void)
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 0bdb43a0aff0..cb32f69d80ba 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -159,7 +159,7 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
return ret;
}
-static int __devexit mc13xxx_spi_remove(struct spi_device *spi)
+static int mc13xxx_spi_remove(struct spi_device *spi)
{
struct mc13xxx *mc13xxx = dev_get_drvdata(&spi->dev);
@@ -176,7 +176,7 @@ static struct spi_driver mc13xxx_spi_driver = {
.of_match_table = mc13xxx_dt_ids,
},
.probe = mc13xxx_spi_probe,
- .remove = __devexit_p(mc13xxx_spi_remove),
+ .remove = mc13xxx_spi_remove,
};
static int __init mc13xxx_init(void)
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 23cec57c02ba..29b8ed21213e 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -464,7 +464,7 @@ static void omap_usbhs_deinit(struct device *dev)
*
* Allocates basic resources for this USB host controller.
*/
-static int __devinit usbhs_omap_probe(struct platform_device *pdev)
+static int usbhs_omap_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usbhs_omap_platform_data *pdata = dev->platform_data;
@@ -652,7 +652,7 @@ end_probe:
*
* Reverses the effect of usbhs_omap_probe().
*/
-static int __devexit usbhs_omap_remove(struct platform_device *pdev)
+static int usbhs_omap_remove(struct platform_device *pdev)
{
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 4b7757b84301..401b976e3aff 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -200,7 +200,7 @@ static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
*
* Allocates basic resources for this USB host controller.
*/
-static int __devinit usbtll_omap_probe(struct platform_device *pdev)
+static int usbtll_omap_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct usbtll_omap_platform_data *pdata = dev->platform_data;
@@ -348,7 +348,7 @@ end:
*
* Reverses the effect of usbtll_omap_probe().
*/
-static int __devexit usbtll_omap_remove(struct platform_device *pdev)
+static int usbtll_omap_remove(struct platform_device *pdev)
{
struct usbtll_omap *tll = platform_get_drvdata(pdev);
@@ -424,7 +424,7 @@ static struct platform_driver usbtll_omap_driver = {
.pm = &usbtllomap_dev_pm_ops,
},
.probe = usbtll_omap_probe,
- .remove = __devexit_p(usbtll_omap_remove),
+ .remove = usbtll_omap_remove,
};
int omap_tll_enable(void)
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c
index 4f8d6e6b19aa..6ffd7a2affdc 100644
--- a/drivers/mfd/palmas.c
+++ b/drivers/mfd/palmas.c
@@ -247,7 +247,7 @@ static struct regmap_irq_chip palmas_irq_chip = {
PALMAS_INT1_MASK),
};
-static void __devinit palmas_dt_to_pdata(struct device_node *node,
+static void palmas_dt_to_pdata(struct device_node *node,
struct palmas_platform_data *pdata)
{
int ret;
@@ -275,7 +275,7 @@ static void __devinit palmas_dt_to_pdata(struct device_node *node,
PALMAS_POWER_CTRL_ENABLE2_MASK;
}
-static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
+static int palmas_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct palmas *palmas;
@@ -492,7 +492,7 @@ static const struct i2c_device_id palmas_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, palmas_i2c_id);
-static struct of_device_id __devinitdata of_palmas_match_tbl[] = {
+static struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas", },
{ /* end */ }
};
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index 3927c17e4175..18b53cb72fea 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -199,7 +199,7 @@ static void pcf50633_adc_irq(int irq, void *data)
kfree(req);
}
-static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
+static int pcf50633_adc_probe(struct platform_device *pdev)
{
struct pcf50633_adc *adc;
@@ -218,7 +218,7 @@ static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
+static int pcf50633_adc_remove(struct platform_device *pdev)
{
struct pcf50633_adc *adc = platform_get_drvdata(pdev);
int i, head;
@@ -246,7 +246,7 @@ static struct platform_driver pcf50633_adc_driver = {
.name = "pcf50633-adc",
},
.probe = pcf50633_adc_probe,
- .remove = __devexit_p(pcf50633_adc_remove),
+ .remove = pcf50633_adc_remove,
};
module_platform_driver(pcf50633_adc_driver);
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 45ce1fb5a549..64803f13bcec 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -191,7 +191,7 @@ static struct regmap_config pcf50633_regmap_config = {
.val_bits = 8,
};
-static int __devinit pcf50633_probe(struct i2c_client *client,
+static int pcf50633_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct pcf50633 *pcf;
@@ -275,7 +275,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
return 0;
}
-static int __devexit pcf50633_remove(struct i2c_client *client)
+static int pcf50633_remove(struct i2c_client *client)
{
struct pcf50633 *pcf = i2c_get_clientdata(client);
int i;
@@ -308,7 +308,7 @@ static struct i2c_driver pcf50633_driver = {
},
.id_table = pcf50633_id_table,
.probe = pcf50633_probe,
- .remove = __devexit_p(pcf50633_remove),
+ .remove = pcf50633_remove,
};
static int __init pcf50633_init(void)
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index e873b15753d8..d4b297cbd801 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -80,7 +80,7 @@ static struct pm8xxx_drvdata pm8921_drvdata = {
.pmic_read_irq_stat = pm8921_read_irq_stat,
};
-static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
+static int pm8921_add_subdevices(const struct pm8921_platform_data
*pdata,
struct pm8921 *pmic,
u32 rev)
@@ -104,7 +104,7 @@ static int __devinit pm8921_add_subdevices(const struct pm8921_platform_data
return ret;
}
-static int __devinit pm8921_probe(struct platform_device *pdev)
+static int pm8921_probe(struct platform_device *pdev)
{
const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
struct pm8921 *pmic;
@@ -165,7 +165,7 @@ err_read_rev:
return rc;
}
-static int __devexit pm8921_remove(struct platform_device *pdev)
+static int pm8921_remove(struct platform_device *pdev)
{
struct pm8xxx_drvdata *drvdata;
struct pm8921 *pmic = NULL;
@@ -187,7 +187,7 @@ static int __devexit pm8921_remove(struct platform_device *pdev)
static struct platform_driver pm8921_driver = {
.probe = pm8921_probe,
- .remove = __devexit_p(pm8921_remove),
+ .remove = pm8921_remove,
.driver = {
.name = "pm8921-core",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/pm8xxx-irq.c b/drivers/mfd/pm8xxx-irq.c
index d452dd013081..1360e20adf11 100644
--- a/drivers/mfd/pm8xxx-irq.c
+++ b/drivers/mfd/pm8xxx-irq.c
@@ -309,7 +309,7 @@ bail_out:
}
EXPORT_SYMBOL_GPL(pm8xxx_get_irq_stat);
-struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
+struct pm_irq_chip * pm8xxx_irq_init(struct device *dev,
const struct pm8xxx_irq_platform_data *pdata)
{
struct pm_irq_chip *chip;
@@ -363,7 +363,7 @@ struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
return chip;
}
-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
+int pm8xxx_irq_exit(struct pm_irq_chip *chip)
{
irq_set_chained_handler(chip->devirq, NULL);
kfree(chip);
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index f1a024ecdb1e..14bdaccefbec 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -246,7 +246,7 @@ static const struct regmap_config rc5t583_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
+static int rc5t583_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rc5t583 *rc5t583;
@@ -303,7 +303,7 @@ err_add_devs:
return ret;
}
-static int __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
+static int rc5t583_i2c_remove(struct i2c_client *i2c)
{
struct rc5t583 *rc5t583 = i2c_get_clientdata(i2c);
@@ -325,7 +325,7 @@ static struct i2c_driver rc5t583_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = rc5t583_i2c_probe,
- .remove = __devexit_p(rc5t583_i2c_remove),
+ .remove = rc5t583_i2c_remove,
.id_table = rc5t583_i2c_id,
};
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index fbabc3cbe350..21b7bef73507 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -72,7 +72,7 @@ static struct mfd_cell rdc321x_sb_cells[] = {
},
};
-static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
+static int rdc321x_sb_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int err;
@@ -91,7 +91,7 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
NULL, 0, NULL);
}
-static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
+static void rdc321x_sb_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
}
@@ -106,7 +106,7 @@ static struct pci_driver rdc321x_sb_driver = {
.name = "RDC321x Southbridge",
.id_table = rdc321x_sb_table,
.probe = rdc321x_sb_probe,
- .remove = __devexit_p(rdc321x_sb_remove),
+ .remove = rdc321x_sb_remove,
};
module_pci_driver(rdc321x_sb_driver);
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
new file mode 100644
index 000000000000..89f046ca9e41
--- /dev/null
+++ b/drivers/mfd/rtl8411.c
@@ -0,0 +1,251 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
+{
+ u8 val;
+
+ rtsx_pci_read_register(pcr, SYS_VER, &val);
+ return val & 0x0F;
+}
+
+static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CD_PAD_CTL,
+ CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
+}
+
+static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
+ BPP_LDO_POWB, BPP_LDO_SUSPEND);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ /* To avoid too large in-rush current */
+ udelay(150);
+
+ err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
+ if (err < 0)
+ return err;
+
+ udelay(150);
+
+ err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
+ if (err < 0)
+ return err;
+
+ udelay(150);
+
+ err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_ON);
+ if (err < 0)
+ return err;
+
+ return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
+}
+
+static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+ int err;
+
+ err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_OFF);
+ if (err < 0)
+ return err;
+
+ return rtsx_pci_write_register(pcr, LDO_CTL,
+ BPP_LDO_POWB, BPP_LDO_SUSPEND);
+}
+
+static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
+{
+ unsigned int card_exist;
+
+ card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+ card_exist &= CARD_EXIST;
+ if (!card_exist) {
+ /* Enable card CD */
+ rtsx_pci_write_register(pcr, CD_PAD_CTL,
+ CD_DISABLE_MASK, CD_ENABLE);
+ /* Enable card interrupt */
+ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
+ return 0;
+ }
+
+ if (hweight32(card_exist) > 1) {
+ rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+ msleep(100);
+
+ card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+ if (card_exist & MS_EXIST)
+ card_exist = MS_EXIST;
+ else if (card_exist & SD_EXIST)
+ card_exist = SD_EXIST;
+ else
+ card_exist = 0;
+
+ rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+ BPP_POWER_MASK, BPP_POWER_OFF);
+
+ dev_dbg(&(pcr->pci->dev),
+ "After CD deglitch, card_exist = 0x%x\n",
+ card_exist);
+ }
+
+ if (card_exist & MS_EXIST) {
+ /* Disable SD interrupt */
+ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
+ rtsx_pci_write_register(pcr, CD_PAD_CTL,
+ CD_DISABLE_MASK, MS_CD_EN_ONLY);
+ } else if (card_exist & SD_EXIST) {
+ /* Disable MS interrupt */
+ rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
+ rtsx_pci_write_register(pcr, CD_PAD_CTL,
+ CD_DISABLE_MASK, SD_CD_EN_ONLY);
+ }
+
+ return card_exist;
+}
+
+static const struct pcr_ops rtl8411_pcr_ops = {
+ .extra_init_hw = rtl8411_extra_init_hw,
+ .optimize_phy = NULL,
+ .turn_on_led = rtl8411_turn_on_led,
+ .turn_off_led = rtl8411_turn_off_led,
+ .enable_auto_blink = rtl8411_enable_auto_blink,
+ .disable_auto_blink = rtl8411_disable_auto_blink,
+ .card_power_on = rtl8411_card_power_on,
+ .card_power_off = rtl8411_card_power_off,
+ .cd_deglitch = rtl8411_cd_deglitch,
+};
+
+/* SD Pull Control Enable:
+ * SD_DAT[3:0] ==> pull up
+ * SD_CD ==> pull up
+ * SD_WP ==> pull up
+ * SD_CMD ==> pull up
+ * SD_CLK ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+ 0,
+};
+
+/* SD Pull Control Disable:
+ * SD_DAT[3:0] ==> pull down
+ * SD_CD ==> pull up
+ * SD_WP ==> pull down
+ * SD_CMD ==> pull down
+ * SD_CLK ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+ 0,
+};
+
+/* MS Pull Control Enable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+ 0,
+};
+
+/* MS Pull Control Disable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+ 0,
+};
+
+void rtl8411_init_params(struct rtsx_pcr *pcr)
+{
+ pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+ pcr->num_slots = 2;
+ pcr->ops = &rtl8411_pcr_ops;
+
+ pcr->ic_version = rtl8411_get_ic_version(pcr);
+ pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
+ pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
+ pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
+ pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
new file mode 100644
index 000000000000..283a4f148084
--- /dev/null
+++ b/drivers/mfd/rts5209.c
@@ -0,0 +1,223 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
+{
+ u8 val;
+
+ val = rtsx_pci_readb(pcr, 0x1C);
+ return val & 0x0F;
+}
+
+static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr)
+{
+ u32 val;
+
+ rtsx_pci_read_config_dword(pcr, 0x724, &val);
+ dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
+
+ if (!(val & 0x80)) {
+ if (val & 0x08)
+ pcr->ms_pmos = false;
+ else
+ pcr->ms_pmos = true;
+ }
+}
+
+static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
+{
+ rtsx_pci_init_cmd(pcr);
+
+ /* Turn off LED */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
+ /* Configure GPIO as output */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
+
+ return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
+}
+
+static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+ int err;
+ u8 pwr_mask, partial_pwr_on, pwr_on;
+
+ pwr_mask = SD_POWER_MASK;
+ partial_pwr_on = SD_PARTIAL_POWER_ON;
+ pwr_on = SD_POWER_ON;
+
+ if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
+ pwr_mask = MS_POWER_MASK;
+ partial_pwr_on = MS_PARTIAL_POWER_ON;
+ pwr_on = MS_POWER_ON;
+ }
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ pwr_mask, partial_pwr_on);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0x04);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ /* To avoid too large in-rush current */
+ udelay(150);
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0x00);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+ u8 pwr_mask, pwr_off;
+
+ pwr_mask = SD_POWER_MASK;
+ pwr_off = SD_POWER_OFF;
+
+ if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
+ pwr_mask = MS_POWER_MASK;
+ pwr_off = MS_POWER_OFF;
+ }
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0X06);
+ return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static const struct pcr_ops rts5209_pcr_ops = {
+ .extra_init_hw = rts5209_extra_init_hw,
+ .optimize_phy = rts5209_optimize_phy,
+ .turn_on_led = rts5209_turn_on_led,
+ .turn_off_led = rts5209_turn_off_led,
+ .enable_auto_blink = rts5209_enable_auto_blink,
+ .disable_auto_blink = rts5209_disable_auto_blink,
+ .card_power_on = rts5209_card_power_on,
+ .card_power_off = rts5209_card_power_off,
+ .cd_deglitch = NULL,
+};
+
+/* SD Pull Control Enable:
+ * SD_DAT[3:0] ==> pull up
+ * SD_CD ==> pull up
+ * SD_WP ==> pull up
+ * SD_CMD ==> pull up
+ * SD_CLK ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+ 0,
+};
+
+/* SD Pull Control Disable:
+ * SD_DAT[3:0] ==> pull down
+ * SD_CD ==> pull up
+ * SD_WP ==> pull down
+ * SD_CMD ==> pull down
+ * SD_CLK ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+ 0,
+};
+
+/* MS Pull Control Enable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+ 0,
+};
+
+/* MS Pull Control Disable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+ 0,
+};
+
+void rts5209_init_params(struct rtsx_pcr *pcr)
+{
+ pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
+ EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
+ pcr->num_slots = 2;
+ pcr->ops = &rts5209_pcr_ops;
+
+ rts5209_init_vendor_cfg(pcr);
+
+ pcr->ic_version = rts5209_get_ic_version(pcr);
+ pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
+ pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
+ pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
+ pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
new file mode 100644
index 000000000000..b9dbab266fda
--- /dev/null
+++ b/drivers/mfd/rts5229.c
@@ -0,0 +1,205 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mfd/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
+{
+ u8 val;
+
+ rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+ return val & 0x0F;
+}
+
+static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
+{
+ rtsx_pci_init_cmd(pcr);
+
+ /* Configure GPIO as output */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
+ /* Switch LDO3318 source from DV33 to card_3v3 */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
+ /* LED shine disabled, set initial shine cycle period */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
+
+ return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
+{
+ /* Optimize RX sensitivity */
+ return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
+}
+
+static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
+}
+
+static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
+}
+
+static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
+}
+
+static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+ return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
+}
+
+static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ SD_POWER_MASK, SD_PARTIAL_POWER_ON);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0x02);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ /* To avoid too large in-rush current */
+ udelay(150);
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ SD_POWER_MASK, SD_POWER_ON);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0x06);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+ SD_POWER_MASK | PMOS_STRG_MASK,
+ SD_POWER_OFF | PMOS_STRG_400mA);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+ LDO3318_PWR_MASK, 0X00);
+ return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static const struct pcr_ops rts5229_pcr_ops = {
+ .extra_init_hw = rts5229_extra_init_hw,
+ .optimize_phy = rts5229_optimize_phy,
+ .turn_on_led = rts5229_turn_on_led,
+ .turn_off_led = rts5229_turn_off_led,
+ .enable_auto_blink = rts5229_enable_auto_blink,
+ .disable_auto_blink = rts5229_disable_auto_blink,
+ .card_power_on = rts5229_card_power_on,
+ .card_power_off = rts5229_card_power_off,
+ .cd_deglitch = NULL,
+};
+
+/* SD Pull Control Enable:
+ * SD_DAT[3:0] ==> pull up
+ * SD_CD ==> pull up
+ * SD_WP ==> pull up
+ * SD_CMD ==> pull up
+ * SD_CLK ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+ 0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
+ 0,
+};
+
+/* SD Pull Control Disable:
+ * SD_DAT[3:0] ==> pull down
+ * SD_CD ==> pull up
+ * SD_WP ==> pull down
+ * SD_CMD ==> pull down
+ * SD_CLK ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+ 0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
+ 0,
+};
+
+/* MS Pull Control Enable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+ 0,
+};
+
+/* MS Pull Control Disable:
+ * MS CD ==> pull up
+ * others ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
+ RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+ RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+ 0,
+};
+
+void rts5229_init_params(struct rtsx_pcr *pcr)
+{
+ pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+ pcr->num_slots = 2;
+ pcr->ops = &rts5229_pcr_ops;
+
+ pcr->ic_version = rts5229_get_ic_version(pcr);
+ if (pcr->ic_version == IC_VER_C) {
+ pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
+ pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
+ } else {
+ pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
+ pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
+ }
+ pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
+ pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
new file mode 100644
index 000000000000..56d4377c62c2
--- /dev/null
+++ b/drivers/mfd/rtsx_pcr.c
@@ -0,0 +1,1251 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+#include "rtsx_pcr.h"
+
+static bool msi_en = true;
+module_param(msi_en, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msi_en, "Enable MSI");
+
+static DEFINE_IDR(rtsx_pci_idr);
+static DEFINE_SPINLOCK(rtsx_pci_lock);
+
+static struct mfd_cell rtsx_pcr_cells[] = {
+ [RTSX_SD_CARD] = {
+ .name = DRV_NAME_RTSX_PCI_SDMMC,
+ },
+ [RTSX_MS_CARD] = {
+ .name = DRV_NAME_RTSX_PCI_MS,
+ },
+};
+
+static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
+ { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr)
+{
+ /* If pci device removed, don't queue idle work any more */
+ if (pcr->remove_pci)
+ return;
+
+ if (pcr->state != PDEV_STAT_RUN) {
+ pcr->state = PDEV_STAT_RUN;
+ if (pcr->ops->enable_auto_blink)
+ pcr->ops->enable_auto_blink(pcr);
+ }
+
+ mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_start_run);
+
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data)
+{
+ int i;
+ u32 val = HAIMR_WRITE_START;
+
+ val |= (u32)(addr & 0x3FFF) << 16;
+ val |= (u32)mask << 8;
+ val |= (u32)data;
+
+ rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+ for (i = 0; i < MAX_RW_REG_CNT; i++) {
+ val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+ if ((val & HAIMR_TRANS_END) == 0) {
+ if (data != (u8)val)
+ return -EIO;
+ return 0;
+ }
+ }
+
+ return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_register);
+
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
+{
+ u32 val = HAIMR_READ_START;
+ int i;
+
+ val |= (u32)(addr & 0x3FFF) << 16;
+ rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+ for (i = 0; i < MAX_RW_REG_CNT; i++) {
+ val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+ if ((val & HAIMR_TRANS_END) == 0)
+ break;
+ }
+
+ if (i >= MAX_RW_REG_CNT)
+ return -ETIMEDOUT;
+
+ if (data)
+ *data = (u8)(val & 0xFF);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
+
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+ int err, i, finished = 0;
+ u8 tmp;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 100000; i++) {
+ err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+ if (err < 0)
+ return err;
+
+ if (!(tmp & 0x80)) {
+ finished = 1;
+ break;
+ }
+ }
+
+ if (!finished)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
+
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+ int err, i, finished = 0;
+ u16 data;
+ u8 *ptr, tmp;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < 100000; i++) {
+ err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+ if (err < 0)
+ return err;
+
+ if (!(tmp & 0x80)) {
+ finished = 1;
+ break;
+ }
+ }
+
+ if (!finished)
+ return -ETIMEDOUT;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0);
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ ptr = rtsx_pci_get_cmd_data(pcr);
+ data = ((u16)ptr[1] << 8) | ptr[0];
+
+ if (val)
+ *val = data;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
+
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
+{
+ rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
+ rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
+
+ rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80);
+ rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_stop_cmd);
+
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+ u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
+{
+ unsigned long flags;
+ u32 val = 0;
+ u32 *ptr = (u32 *)(pcr->host_cmds_ptr);
+
+ val |= (u32)(cmd_type & 0x03) << 30;
+ val |= (u32)(reg_addr & 0x3FFF) << 16;
+ val |= (u32)mask << 8;
+ val |= (u32)data;
+
+ spin_lock_irqsave(&pcr->lock, flags);
+ ptr += pcr->ci;
+ if (pcr->ci < (HOST_CMDS_BUF_LEN / 4)) {
+ put_unaligned_le32(val, ptr);
+ ptr++;
+ pcr->ci++;
+ }
+ spin_unlock_irqrestore(&pcr->lock, flags);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_add_cmd);
+
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr)
+{
+ u32 val = 1 << 31;
+
+ rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+ val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+ /* Hardware Auto Response */
+ val |= 0x40000000;
+ rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd_no_wait);
+
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
+{
+ struct completion trans_done;
+ u32 val = 1 << 31;
+ long timeleft;
+ unsigned long flags;
+ int err = 0;
+
+ spin_lock_irqsave(&pcr->lock, flags);
+
+ /* set up data structures for the wakeup system */
+ pcr->done = &trans_done;
+ pcr->trans_result = TRANS_NOT_READY;
+ init_completion(&trans_done);
+
+ rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+ val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+ /* Hardware Auto Response */
+ val |= 0x40000000;
+ rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+ /* Wait for TRANS_OK_INT */
+ timeleft = wait_for_completion_interruptible_timeout(
+ &trans_done, msecs_to_jiffies(timeout));
+ if (timeleft <= 0) {
+ dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
+ __func__, __LINE__);
+ err = -ETIMEDOUT;
+ goto finish_send_cmd;
+ }
+
+ spin_lock_irqsave(&pcr->lock, flags);
+ if (pcr->trans_result == TRANS_RESULT_FAIL)
+ err = -EINVAL;
+ else if (pcr->trans_result == TRANS_RESULT_OK)
+ err = 0;
+ else if (pcr->trans_result == TRANS_NO_DEVICE)
+ err = -ENODEV;
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+finish_send_cmd:
+ spin_lock_irqsave(&pcr->lock, flags);
+ pcr->done = NULL;
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+ if ((err < 0) && (err != -ENODEV))
+ rtsx_pci_stop_cmd(pcr);
+
+ if (pcr->finish_me)
+ complete(pcr->finish_me);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd);
+
+static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
+ dma_addr_t addr, unsigned int len, int end)
+{
+ u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi;
+ u64 val;
+ u8 option = SG_VALID | SG_TRANS_DATA;
+
+ dev_dbg(&(pcr->pci->dev), "DMA addr: 0x%x, Len: 0x%x\n",
+ (unsigned int)addr, len);
+
+ if (end)
+ option |= SG_END;
+ val = ((u64)addr << 32) | ((u64)len << 12) | option;
+
+ put_unaligned_le64(val, ptr);
+ ptr++;
+ pcr->sgi++;
+}
+
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read, int timeout)
+{
+ struct completion trans_done;
+ u8 dir;
+ int err = 0, i, count;
+ long timeleft;
+ unsigned long flags;
+ struct scatterlist *sg;
+ enum dma_data_direction dma_dir;
+ u32 val;
+ dma_addr_t addr;
+ unsigned int len;
+
+ dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+
+ /* don't transfer data during abort processing */
+ if (pcr->remove_pci)
+ return -EINVAL;
+
+ if ((sglist == NULL) || (num_sg <= 0))
+ return -EINVAL;
+
+ if (read) {
+ dir = DEVICE_TO_HOST;
+ dma_dir = DMA_FROM_DEVICE;
+ } else {
+ dir = HOST_TO_DEVICE;
+ dma_dir = DMA_TO_DEVICE;
+ }
+
+ count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+ if (count < 1) {
+ dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
+ return -EINVAL;
+ }
+ dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
+
+ val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
+ pcr->sgi = 0;
+ for_each_sg(sglist, sg, count, i) {
+ addr = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+ rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
+ }
+
+ spin_lock_irqsave(&pcr->lock, flags);
+
+ pcr->done = &trans_done;
+ pcr->trans_result = TRANS_NOT_READY;
+ init_completion(&trans_done);
+ rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
+ rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
+
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+ timeleft = wait_for_completion_interruptible_timeout(
+ &trans_done, msecs_to_jiffies(timeout));
+ if (timeleft <= 0) {
+ dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
+ __func__, __LINE__);
+ err = -ETIMEDOUT;
+ goto out;
+ }
+
+ spin_lock_irqsave(&pcr->lock, flags);
+
+ if (pcr->trans_result == TRANS_RESULT_FAIL)
+ err = -EINVAL;
+ else if (pcr->trans_result == TRANS_NO_DEVICE)
+ err = -ENODEV;
+
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+out:
+ spin_lock_irqsave(&pcr->lock, flags);
+ pcr->done = NULL;
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+ dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
+
+ if ((err < 0) && (err != -ENODEV))
+ rtsx_pci_stop_cmd(pcr);
+
+ if (pcr->finish_me)
+ complete(pcr->finish_me);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+ int err;
+ int i, j;
+ u16 reg;
+ u8 *ptr;
+
+ if (buf_len > 512)
+ buf_len = 512;
+
+ ptr = buf;
+ reg = PPBUF_BASE2;
+ for (i = 0; i < buf_len / 256; i++) {
+ rtsx_pci_init_cmd(pcr);
+
+ for (j = 0; j < 256; j++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 250);
+ if (err < 0)
+ return err;
+
+ memcpy(ptr, rtsx_pci_get_cmd_data(pcr), 256);
+ ptr += 256;
+ }
+
+ if (buf_len % 256) {
+ rtsx_pci_init_cmd(pcr);
+
+ for (j = 0; j < buf_len % 256; j++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 250);
+ if (err < 0)
+ return err;
+ }
+
+ memcpy(ptr, rtsx_pci_get_cmd_data(pcr), buf_len % 256);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_ppbuf);
+
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+ int err;
+ int i, j;
+ u16 reg;
+ u8 *ptr;
+
+ if (buf_len > 512)
+ buf_len = 512;
+
+ ptr = buf;
+ reg = PPBUF_BASE2;
+ for (i = 0; i < buf_len / 256; i++) {
+ rtsx_pci_init_cmd(pcr);
+
+ for (j = 0; j < 256; j++) {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ reg++, 0xFF, *ptr);
+ ptr++;
+ }
+
+ err = rtsx_pci_send_cmd(pcr, 250);
+ if (err < 0)
+ return err;
+ }
+
+ if (buf_len % 256) {
+ rtsx_pci_init_cmd(pcr);
+
+ for (j = 0; j < buf_len % 256; j++) {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ reg++, 0xFF, *ptr);
+ ptr++;
+ }
+
+ err = rtsx_pci_send_cmd(pcr, 250);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
+
+static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
+{
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+
+ while (*tbl & 0xFFFF0000) {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ (u16)(*tbl >> 16), 0xFF, (u8)(*tbl));
+ tbl++;
+ }
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
+{
+ const u32 *tbl;
+
+ if (card == RTSX_SD_CARD)
+ tbl = pcr->sd_pull_ctl_enable_tbl;
+ else if (card == RTSX_MS_CARD)
+ tbl = pcr->ms_pull_ctl_enable_tbl;
+ else
+ return -EINVAL;
+
+ return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_enable);
+
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card)
+{
+ const u32 *tbl;
+
+ if (card == RTSX_SD_CARD)
+ tbl = pcr->sd_pull_ctl_disable_tbl;
+ else if (card == RTSX_MS_CARD)
+ tbl = pcr->ms_pull_ctl_disable_tbl;
+ else
+ return -EINVAL;
+
+
+ return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
+
+static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
+{
+ pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
+
+ if (pcr->num_slots > 1)
+ pcr->bier |= MS_INT_EN;
+
+ /* Enable Bus Interrupt */
+ rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
+
+ dev_dbg(&(pcr->pci->dev), "RTSX_BIER: 0x%08x\n", pcr->bier);
+}
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+ return ((depth > 1) ? (depth - 1) : depth);
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+ if (div > CLK_DIV_1) {
+ if (ssc_depth > (div - 1))
+ ssc_depth -= (div - 1);
+ else
+ ssc_depth = SSC_DEPTH_4M;
+ }
+
+ return ssc_depth;
+}
+
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+ u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+ int err, clk;
+ u8 N, min_N, max_N, clk_divider;
+ u8 mcu_cnt, div, max_div;
+ u8 depth[] = {
+ [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
+ [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
+ [RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
+ [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K,
+ [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K,
+ };
+
+ if (initial_mode) {
+ /* We use 250k(around) here, in initial stage */
+ clk_divider = SD_CLK_DIVIDE_128;
+ card_clock = 30000000;
+ } else {
+ clk_divider = SD_CLK_DIVIDE_0;
+ }
+ err = rtsx_pci_write_register(pcr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, clk_divider);
+ if (err < 0)
+ return err;
+
+ card_clock /= 1000000;
+ dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock);
+
+ min_N = 80;
+ max_N = 208;
+ max_div = CLK_DIV_8;
+
+ clk = card_clock;
+ if (!initial_mode && double_clk)
+ clk = card_clock * 2;
+ dev_dbg(&(pcr->pci->dev),
+ "Internal SSC clock: %dMHz (cur_clock = %d)\n",
+ clk, pcr->cur_clock);
+
+ if (clk == pcr->cur_clock)
+ return 0;
+
+ N = (u8)(clk - 2);
+ if ((clk <= 2) || (N > max_N))
+ return -EINVAL;
+
+ mcu_cnt = (u8)(125/clk + 3);
+ if (mcu_cnt > 15)
+ mcu_cnt = 15;
+
+ /* Make sure that the SSC clock div_n is equal or greater than min_N */
+ div = CLK_DIV_1;
+ while ((N < min_N) && (div < max_div)) {
+ N = (N + 2) * 2 - 2;
+ div++;
+ }
+ dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div);
+
+ ssc_depth = depth[ssc_depth];
+ if (double_clk)
+ ssc_depth = double_ssc_depth(ssc_depth);
+
+ ssc_depth = revise_ssc_depth(ssc_depth, div);
+ dev_dbg(&(pcr->pci->dev), "ssc_depth = %d\n", ssc_depth);
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+ CLK_LOW_FREQ, CLK_LOW_FREQ);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV,
+ 0xFF, (div << 4) | mcu_cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2,
+ SSC_DEPTH_MASK, ssc_depth);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+ if (vpclk) {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, PHASE_NOT_RESET);
+ }
+
+ err = rtsx_pci_send_cmd(pcr, 2000);
+ if (err < 0)
+ return err;
+
+ /* Wait SSC clock stable */
+ udelay(10);
+ err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
+ if (err < 0)
+ return err;
+
+ pcr->cur_clock = clk;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_clock);
+
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+ if (pcr->ops->card_power_on)
+ return pcr->ops->card_power_on(pcr, card);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_on);
+
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+ if (pcr->ops->card_power_off)
+ return pcr->ops->card_power_off(pcr, card);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
+
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
+{
+ unsigned int val;
+
+ val = rtsx_pci_readl(pcr, RTSX_BIPR);
+ if (pcr->ops->cd_deglitch)
+ val = pcr->ops->cd_deglitch(pcr);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_exist);
+
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr)
+{
+ struct completion finish;
+
+ pcr->finish_me = &finish;
+ init_completion(&finish);
+
+ if (pcr->done)
+ complete(pcr->done);
+
+ if (!pcr->remove_pci)
+ rtsx_pci_stop_cmd(pcr);
+
+ wait_for_completion_interruptible_timeout(&finish,
+ msecs_to_jiffies(2));
+ pcr->finish_me = NULL;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_complete_unfinished_transfer);
+
+static void rtsx_pci_card_detect(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+ struct rtsx_pcr *pcr;
+ unsigned long flags;
+ unsigned int card_detect = 0;
+ u32 irq_status;
+
+ dwork = to_delayed_work(work);
+ pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
+
+ dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+
+ spin_lock_irqsave(&pcr->lock, flags);
+
+ irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
+ dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status);
+
+ if (pcr->card_inserted || pcr->card_removed) {
+ dev_dbg(&(pcr->pci->dev),
+ "card_inserted: 0x%x, card_removed: 0x%x\n",
+ pcr->card_inserted, pcr->card_removed);
+
+ if (pcr->ops->cd_deglitch)
+ pcr->card_inserted = pcr->ops->cd_deglitch(pcr);
+
+ card_detect = pcr->card_inserted | pcr->card_removed;
+ pcr->card_inserted = 0;
+ pcr->card_removed = 0;
+ }
+
+ spin_unlock_irqrestore(&pcr->lock, flags);
+
+ if (card_detect & SD_EXIST)
+ pcr->slots[RTSX_SD_CARD].card_event(
+ pcr->slots[RTSX_SD_CARD].p_dev);
+ if (card_detect & MS_EXIST)
+ pcr->slots[RTSX_MS_CARD].card_event(
+ pcr->slots[RTSX_MS_CARD].p_dev);
+}
+
+static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
+{
+ struct rtsx_pcr *pcr = dev_id;
+ u32 int_reg;
+
+ if (!pcr)
+ return IRQ_NONE;
+
+ spin_lock(&pcr->lock);
+
+ int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
+ /* Clear interrupt flag */
+ rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
+ if ((int_reg & pcr->bier) == 0) {
+ spin_unlock(&pcr->lock);
+ return IRQ_NONE;
+ }
+ if (int_reg == 0xFFFFFFFF) {
+ spin_unlock(&pcr->lock);
+ return IRQ_HANDLED;
+ }
+
+ int_reg &= (pcr->bier | 0x7FFFFF);
+
+ if (int_reg & SD_INT) {
+ if (int_reg & SD_EXIST) {
+ pcr->card_inserted |= SD_EXIST;
+ } else {
+ pcr->card_removed |= SD_EXIST;
+ pcr->card_inserted &= ~SD_EXIST;
+ }
+ }
+
+ if (int_reg & MS_INT) {
+ if (int_reg & MS_EXIST) {
+ pcr->card_inserted |= MS_EXIST;
+ } else {
+ pcr->card_removed |= MS_EXIST;
+ pcr->card_inserted &= ~MS_EXIST;
+ }
+ }
+
+ if (pcr->card_inserted || pcr->card_removed)
+ schedule_delayed_work(&pcr->carddet_work,
+ msecs_to_jiffies(200));
+
+ if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
+ if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
+ pcr->trans_result = TRANS_RESULT_FAIL;
+ if (pcr->done)
+ complete(pcr->done);
+ } else if (int_reg & TRANS_OK_INT) {
+ pcr->trans_result = TRANS_RESULT_OK;
+ if (pcr->done)
+ complete(pcr->done);
+ }
+ }
+
+ spin_unlock(&pcr->lock);
+ return IRQ_HANDLED;
+}
+
+static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
+{
+ dev_info(&(pcr->pci->dev), "%s: pcr->msi_en = %d, pci->irq = %d\n",
+ __func__, pcr->msi_en, pcr->pci->irq);
+
+ if (request_irq(pcr->pci->irq, rtsx_pci_isr,
+ pcr->msi_en ? 0 : IRQF_SHARED,
+ DRV_NAME_RTSX_PCI, pcr)) {
+ dev_err(&(pcr->pci->dev),
+ "rtsx_sdmmc: unable to grab IRQ %d, disabling device\n",
+ pcr->pci->irq);
+ return -1;
+ }
+
+ pcr->irq = pcr->pci->irq;
+ pci_intx(pcr->pci, !pcr->msi_en);
+
+ return 0;
+}
+
+static void rtsx_pci_idle_work(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
+
+ dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ pcr->state = PDEV_STAT_IDLE;
+
+ if (pcr->ops->disable_auto_blink)
+ pcr->ops->disable_auto_blink(pcr);
+ if (pcr->ops->turn_off_led)
+ pcr->ops->turn_off_led(pcr);
+
+ mutex_unlock(&pcr->pcr_mutex);
+}
+
+static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
+{
+ int err;
+
+ rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+ rtsx_pci_enable_bus_int(pcr);
+
+ /* Power on SSC */
+ err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0);
+ if (err < 0)
+ return err;
+
+ /* Wait SSC power stable */
+ udelay(200);
+
+ if (pcr->ops->optimize_phy) {
+ err = pcr->ops->optimize_phy(pcr);
+ if (err < 0)
+ return err;
+ }
+
+ rtsx_pci_init_cmd(pcr);
+
+ /* Set mcu_cnt to 7 to ensure data can be sampled properly */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV, 0x07, 0x07);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, HOST_SLEEP_STATE, 0x03, 0x00);
+ /* Disable card clock */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 0x1E, 0);
+ /* Reset ASPM state to default value */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+ /* Reset delink mode */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
+ /* Card driving select */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+ 0x07, DRIVER_TYPE_D);
+ /* Enable SSC Clock */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
+ 0xFF, SSC_8X_EN | SSC_SEL_4M);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12);
+ /* Disable cd_pwr_save */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10);
+ /* Clear Link Ready Interrupt */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+ LINK_RDY_INT, LINK_RDY_INT);
+ /* Enlarge the estimation window of PERST# glitch
+ * to reduce the chance of invalid card interrupt
+ */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+ /* Update RC oscillator to 400k
+ * bit[0] F_HIGH: for RC oscillator, Rst_value is 1'b1
+ * 1: 2M 0: 400k
+ */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RCCTL, 0x01, 0x00);
+ /* Set interrupt write clear
+ * bit 1: U_elbi_if_rd_clr_en
+ * 1: Enable ELBI interrupt[31:22] & [7:0] flag read clear
+ * 0: ELBI interrupt flag[31:22] & [7:0] only can be write clear
+ */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, NFTS_TX_CTRL, 0x02, 0);
+ /* Force CLKREQ# PIN to drive 0 to request clock */
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ /* Enable clk_request_n to enable clock power management */
+ rtsx_pci_write_config_byte(pcr, 0x81, 1);
+ /* Enter L1 when host tx idle */
+ rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
+
+ if (pcr->ops->extra_init_hw) {
+ err = pcr->ops->extra_init_hw(pcr);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
+{
+ int err;
+
+ spin_lock_init(&pcr->lock);
+ mutex_init(&pcr->pcr_mutex);
+
+ switch (PCI_PID(pcr)) {
+ default:
+ case 0x5209:
+ rts5209_init_params(pcr);
+ break;
+
+ case 0x5229:
+ rts5229_init_params(pcr);
+ break;
+
+ case 0x5289:
+ rtl8411_init_params(pcr);
+ break;
+ }
+
+ dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
+ PCI_PID(pcr), pcr->ic_version);
+
+ pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
+ GFP_KERNEL);
+ if (!pcr->slots)
+ return -ENOMEM;
+
+ pcr->state = PDEV_STAT_IDLE;
+ err = rtsx_pci_init_hw(pcr);
+ if (err < 0) {
+ kfree(pcr->slots);
+ return err;
+ }
+
+ return 0;
+}
+
+static int __devinit rtsx_pci_probe(struct pci_dev *pcidev,
+ const struct pci_device_id *id)
+{
+ struct rtsx_pcr *pcr;
+ struct pcr_handle *handle;
+ u32 base, len;
+ int ret, i;
+
+ dev_dbg(&(pcidev->dev),
+ ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
+ pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
+ (int)pcidev->revision);
+
+ ret = pci_enable_device(pcidev);
+ if (ret)
+ return ret;
+
+ ret = pci_request_regions(pcidev, DRV_NAME_RTSX_PCI);
+ if (ret)
+ goto disable;
+
+ pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
+ if (!pcr) {
+ ret = -ENOMEM;
+ goto release_pci;
+ }
+
+ handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+ if (!handle) {
+ ret = -ENOMEM;
+ goto free_pcr;
+ }
+ handle->pcr = pcr;
+
+ if (!idr_pre_get(&rtsx_pci_idr, GFP_KERNEL)) {
+ ret = -ENOMEM;
+ goto free_handle;
+ }
+
+ spin_lock(&rtsx_pci_lock);
+ ret = idr_get_new(&rtsx_pci_idr, pcr, &pcr->id);
+ spin_unlock(&rtsx_pci_lock);
+ if (ret)
+ goto free_handle;
+
+ pcr->pci = pcidev;
+ dev_set_drvdata(&pcidev->dev, handle);
+
+ len = pci_resource_len(pcidev, 0);
+ base = pci_resource_start(pcidev, 0);
+ pcr->remap_addr = ioremap_nocache(base, len);
+ if (!pcr->remap_addr) {
+ ret = -ENOMEM;
+ goto free_host;
+ }
+
+ pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
+ RTSX_RESV_BUF_LEN, &(pcr->rtsx_resv_buf_addr),
+ GFP_KERNEL);
+ if (pcr->rtsx_resv_buf == NULL) {
+ ret = -ENXIO;
+ goto unmap;
+ }
+ pcr->host_cmds_ptr = pcr->rtsx_resv_buf;
+ pcr->host_cmds_addr = pcr->rtsx_resv_buf_addr;
+ pcr->host_sg_tbl_ptr = pcr->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
+ pcr->host_sg_tbl_addr = pcr->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
+
+ pcr->card_inserted = 0;
+ pcr->card_removed = 0;
+ INIT_DELAYED_WORK(&pcr->carddet_work, rtsx_pci_card_detect);
+ INIT_DELAYED_WORK(&pcr->idle_work, rtsx_pci_idle_work);
+
+ pcr->msi_en = msi_en;
+ if (pcr->msi_en) {
+ ret = pci_enable_msi(pcidev);
+ if (ret < 0)
+ pcr->msi_en = false;
+ }
+
+ ret = rtsx_pci_acquire_irq(pcr);
+ if (ret < 0)
+ goto free_dma;
+
+ pci_set_master(pcidev);
+ synchronize_irq(pcr->irq);
+
+ ret = rtsx_pci_init_chip(pcr);
+ if (ret < 0)
+ goto disable_irq;
+
+ for (i = 0; i < ARRAY_SIZE(rtsx_pcr_cells); i++) {
+ rtsx_pcr_cells[i].platform_data = handle;
+ rtsx_pcr_cells[i].pdata_size = sizeof(*handle);
+ }
+ ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
+ ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
+ if (ret < 0)
+ goto disable_irq;
+
+ schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+ return 0;
+
+disable_irq:
+ free_irq(pcr->irq, (void *)pcr);
+free_dma:
+ dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+ pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+unmap:
+ iounmap(pcr->remap_addr);
+free_host:
+ dev_set_drvdata(&pcidev->dev, NULL);
+free_handle:
+ kfree(handle);
+free_pcr:
+ kfree(pcr);
+release_pci:
+ pci_release_regions(pcidev);
+disable:
+ pci_disable_device(pcidev);
+
+ return ret;
+}
+
+static void __devexit rtsx_pci_remove(struct pci_dev *pcidev)
+{
+ struct pcr_handle *handle = pci_get_drvdata(pcidev);
+ struct rtsx_pcr *pcr = handle->pcr;
+
+ pcr->remove_pci = true;
+
+ cancel_delayed_work(&pcr->carddet_work);
+ cancel_delayed_work(&pcr->idle_work);
+
+ mfd_remove_devices(&pcidev->dev);
+
+ dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+ pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+ free_irq(pcr->irq, (void *)pcr);
+ if (pcr->msi_en)
+ pci_disable_msi(pcr->pci);
+ iounmap(pcr->remap_addr);
+
+ dev_set_drvdata(&pcidev->dev, NULL);
+ pci_release_regions(pcidev);
+ pci_disable_device(pcidev);
+
+ spin_lock(&rtsx_pci_lock);
+ idr_remove(&rtsx_pci_idr, pcr->id);
+ spin_unlock(&rtsx_pci_lock);
+
+ kfree(pcr->slots);
+ kfree(pcr);
+ kfree(handle);
+
+ dev_dbg(&(pcidev->dev),
+ ": Realtek PCI-E Card Reader at %s [%04x:%04x] has been removed\n",
+ pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
+}
+
+#ifdef CONFIG_PM
+
+static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
+{
+ struct pcr_handle *handle;
+ struct rtsx_pcr *pcr;
+ int ret = 0;
+
+ dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+ handle = pci_get_drvdata(pcidev);
+ pcr = handle->pcr;
+
+ cancel_delayed_work(&pcr->carddet_work);
+ cancel_delayed_work(&pcr->idle_work);
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ if (pcr->ops->turn_off_led)
+ pcr->ops->turn_off_led(pcr);
+
+ rtsx_pci_writel(pcr, RTSX_BIER, 0);
+ pcr->bier = 0;
+
+ rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
+ rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x02);
+
+ pci_save_state(pcidev);
+ pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
+ pci_disable_device(pcidev);
+ pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
+
+ mutex_unlock(&pcr->pcr_mutex);
+ return ret;
+}
+
+static int rtsx_pci_resume(struct pci_dev *pcidev)
+{
+ struct pcr_handle *handle;
+ struct rtsx_pcr *pcr;
+ int ret = 0;
+
+ dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+ handle = pci_get_drvdata(pcidev);
+ pcr = handle->pcr;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ pci_set_power_state(pcidev, PCI_D0);
+ pci_restore_state(pcidev);
+ ret = pci_enable_device(pcidev);
+ if (ret)
+ goto out;
+ pci_set_master(pcidev);
+
+ ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00);
+ if (ret)
+ goto out;
+
+ ret = rtsx_pci_init_hw(pcr);
+ if (ret)
+ goto out;
+
+ schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+out:
+ mutex_unlock(&pcr->pcr_mutex);
+ return ret;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_pci_suspend NULL
+#define rtsx_pci_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver rtsx_pci_driver = {
+ .name = DRV_NAME_RTSX_PCI,
+ .id_table = rtsx_pci_ids,
+ .probe = rtsx_pci_probe,
+ .remove = __devexit_p(rtsx_pci_remove),
+ .suspend = rtsx_pci_suspend,
+ .resume = rtsx_pci_resume,
+};
+module_pci_driver(rtsx_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E Card Reader Driver");
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
new file mode 100644
index 000000000000..12462c1df1a9
--- /dev/null
+++ b/drivers/mfd/rtsx_pcr.h
@@ -0,0 +1,32 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_PCR_H
+#define __RTSX_PCR_H
+
+#include <linux/mfd/rtsx_pci.h>
+
+void rts5209_init_params(struct rtsx_pcr *pcr);
+void rts5229_init_params(struct rtsx_pcr *pcr);
+void rtl8411_init_params(struct rtsx_pcr *pcr);
+
+#endif
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index d927dd49acb3..9816c232e583 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1014,7 +1014,7 @@ static struct gpio_chip gpio_chip_template = {
.get = sm501_gpio_get,
};
-static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
+static int sm501_gpio_register_chip(struct sm501_devdata *sm,
struct sm501_gpio *gpio,
struct sm501_gpio_chip *chip)
{
@@ -1042,7 +1042,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
return gpiochip_add(gchip);
}
-static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
+static int sm501_register_gpio(struct sm501_devdata *sm)
{
struct sm501_gpio *gpio = &sm->gpio;
resource_size_t iobase = sm->io_res->start + SM501_GPIO;
@@ -1313,7 +1313,7 @@ static unsigned int sm501_mem_local[] = {
* Common init code for an SM501
*/
-static int __devinit sm501_init_dev(struct sm501_devdata *sm)
+static int sm501_init_dev(struct sm501_devdata *sm)
{
struct sm501_initdata *idata;
struct sm501_platdata *pdata;
@@ -1389,7 +1389,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
return 0;
}
-static int __devinit sm501_plat_probe(struct platform_device *dev)
+static int sm501_plat_probe(struct platform_device *dev)
{
struct sm501_devdata *sm;
int ret;
@@ -1578,7 +1578,7 @@ static struct sm501_platdata sm501_pci_platdata = {
.gpio_base = -1,
};
-static int __devinit sm501_pci_probe(struct pci_dev *dev,
+static int sm501_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct sm501_devdata *sm;
@@ -1685,7 +1685,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
sm501_gpio_remove(sm);
}
-static void __devexit sm501_pci_remove(struct pci_dev *dev)
+static void sm501_pci_remove(struct pci_dev *dev)
{
struct sm501_devdata *sm = pci_get_drvdata(dev);
@@ -1723,12 +1723,12 @@ static struct pci_driver sm501_pci_driver = {
.name = "sm501",
.id_table = sm501_pci_tbl,
.probe = sm501_pci_probe,
- .remove = __devexit_p(sm501_pci_remove),
+ .remove = sm501_pci_remove,
};
MODULE_ALIAS("platform:sm501");
-static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+static struct of_device_id of_sm501_match_tbl[] = {
{ .compatible = "smi,sm501", },
{ /* end */ }
};
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index d35da6820bea..d6284cacd27a 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -69,7 +69,7 @@ static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
return NULL;
}
-static int __devinit sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
+static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
{
struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
struct sta2x11_instance *instance;
@@ -89,7 +89,7 @@ static int __devinit sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
return 0;
}
-static int __devexit mfd_remove(struct pci_dev *pdev)
+static int mfd_remove(struct pci_dev *pdev)
{
struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
@@ -305,7 +305,7 @@ enum bar1_cells {
.flags = IORESOURCE_MEM, \
}
-static const __devinitconst struct resource gpio_resources[] = {
+static const struct resource gpio_resources[] = {
{
.name = "sta2x11_gpio", /* 4 consecutive cells, 1 driver */
.start = 0,
@@ -313,31 +313,31 @@ static const __devinitconst struct resource gpio_resources[] = {
.flags = IORESOURCE_MEM,
}
};
-static const __devinitconst struct resource sctl_resources[] = {
+static const struct resource sctl_resources[] = {
CELL_4K("sta2x11-sctl", STA2X11_SCTL),
};
-static const __devinitconst struct resource scr_resources[] = {
+static const struct resource scr_resources[] = {
CELL_4K("sta2x11-scr", STA2X11_SCR),
};
-static const __devinitconst struct resource time_resources[] = {
+static const struct resource time_resources[] = {
CELL_4K("sta2x11-time", STA2X11_TIME),
};
-static const __devinitconst struct resource apbreg_resources[] = {
+static const struct resource apbreg_resources[] = {
CELL_4K("sta2x11-apbreg", STA2X11_APBREG),
};
#define DEV(_name, _r) \
{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
-static __devinitdata struct mfd_cell sta2x11_mfd_bar0[] = {
+static struct mfd_cell sta2x11_mfd_bar0[] = {
DEV("sta2x11-gpio", gpio_resources), /* offset 0: we add pdata later */
DEV("sta2x11-sctl", sctl_resources),
DEV("sta2x11-scr", scr_resources),
DEV("sta2x11-time", time_resources),
};
-static __devinitdata struct mfd_cell sta2x11_mfd_bar1[] = {
+static struct mfd_cell sta2x11_mfd_bar1[] = {
DEV("sta2x11-apbreg", apbreg_resources),
};
@@ -363,7 +363,7 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
return 0;
}
-static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
+static int sta2x11_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
int err, i;
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index 947a06a1845f..36df18778029 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -52,7 +52,7 @@ static struct stmpe_client_info i2c_ci = {
.write_block = i2c_block_write,
};
-static int __devinit
+static int
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
i2c_ci.data = (void *)id;
@@ -63,7 +63,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
return stmpe_probe(&i2c_ci, id->driver_data);
}
-static int __devexit stmpe_i2c_remove(struct i2c_client *i2c)
+static int stmpe_i2c_remove(struct i2c_client *i2c)
{
struct stmpe *stmpe = dev_get_drvdata(&i2c->dev);
@@ -88,7 +88,7 @@ static struct i2c_driver stmpe_i2c_driver = {
.driver.pm = &stmpe_dev_pm_ops,
#endif
.probe = stmpe_i2c_probe,
- .remove = __devexit_p(stmpe_i2c_remove),
+ .remove = stmpe_i2c_remove,
.id_table = stmpe_i2c_id,
};
diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c
index 9edfe864cc05..973659f8abd9 100644
--- a/drivers/mfd/stmpe-spi.c
+++ b/drivers/mfd/stmpe-spi.c
@@ -82,7 +82,7 @@ static struct stmpe_client_info spi_ci = {
.init = spi_init,
};
-static int __devinit
+static int
stmpe_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
@@ -101,7 +101,7 @@ stmpe_spi_probe(struct spi_device *spi)
return stmpe_probe(&spi_ci, id->driver_data);
}
-static int __devexit stmpe_spi_remove(struct spi_device *spi)
+static int stmpe_spi_remove(struct spi_device *spi)
{
struct stmpe *stmpe = dev_get_drvdata(&spi->dev);
@@ -128,7 +128,7 @@ static struct spi_driver stmpe_spi_driver = {
#endif
},
.probe = stmpe_spi_probe,
- .remove = __devexit_p(stmpe_spi_remove),
+ .remove = stmpe_spi_remove,
.id_table = stmpe_spi_id,
};
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index c94f521f392c..79e88d1fd99a 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -294,12 +294,14 @@ static struct resource stmpe_gpio_resources[] = {
static struct mfd_cell stmpe_gpio_cell = {
.name = "stmpe-gpio",
+ .of_compatible = "st,stmpe-gpio",
.resources = stmpe_gpio_resources,
.num_resources = ARRAY_SIZE(stmpe_gpio_resources),
};
static struct mfd_cell stmpe_gpio_cell_noirq = {
.name = "stmpe-gpio",
+ .of_compatible = "st,stmpe-gpio",
/* gpio cell resources consist of an irq only so no resources here */
};
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 65fe609026cc..3f10591ea94e 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -97,7 +97,7 @@ static struct regmap_config syscon_regmap_config = {
.reg_stride = 4,
};
-static int __devinit syscon_probe(struct platform_device *pdev)
+static int syscon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
@@ -138,7 +138,7 @@ static int __devinit syscon_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit syscon_remove(struct platform_device *pdev)
+static int syscon_remove(struct platform_device *pdev)
{
struct syscon *syscon;
@@ -156,7 +156,7 @@ static struct platform_driver syscon_driver = {
.of_match_table = of_syscon_match,
},
.probe = syscon_probe,
- .remove = __devexit_p(syscon_remove),
+ .remove = syscon_remove,
};
static int __init syscon_init(void)
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index 8f4c853ca116..a06d66b929b1 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -282,7 +282,7 @@ static int tc3589x_chip_init(struct tc3589x *tc3589x)
return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1);
}
-static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
+static int tc3589x_device_init(struct tc3589x *tc3589x)
{
int ret = 0;
unsigned int blocks = tc3589x->pdata->block;
@@ -329,7 +329,7 @@ static int tc3589x_of_probe(struct device_node *np,
return 0;
}
-static int __devinit tc3589x_probe(struct i2c_client *i2c,
+static int tc3589x_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tc3589x_platform_data *pdata = i2c->dev.platform_data;
@@ -402,7 +402,7 @@ out_free:
return ret;
}
-static int __devexit tc3589x_remove(struct i2c_client *client)
+static int tc3589x_remove(struct i2c_client *client)
{
struct tc3589x *tc3589x = i2c_get_clientdata(client);
@@ -458,7 +458,7 @@ static struct i2c_driver tc3589x_driver = {
.driver.owner = THIS_MODULE,
.driver.pm = &tc3589x_dev_pm_ops,
.probe = tc3589x_probe,
- .remove = __devexit_p(tc3589x_remove),
+ .remove = tc3589x_remove,
.id_table = tc3589x_id,
};
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 413c891102f8..366f7b906278 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -138,7 +138,7 @@ static struct mfd_cell tc6387xb_cells[] = {
},
};
-static int __devinit tc6387xb_probe(struct platform_device *dev)
+static int tc6387xb_probe(struct platform_device *dev)
{
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
struct resource *iomem, *rscr;
@@ -208,7 +208,7 @@ err_no_irq:
return ret;
}
-static int __devexit tc6387xb_remove(struct platform_device *dev)
+static int tc6387xb_remove(struct platform_device *dev)
{
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
@@ -229,7 +229,7 @@ static struct platform_driver tc6387xb_platform_driver = {
.name = "tc6387xb",
},
.probe = tc6387xb_probe,
- .remove = __devexit_p(tc6387xb_remove),
+ .remove = tc6387xb_remove,
.suspend = tc6387xb_suspend,
.resume = tc6387xb_resume,
};
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index dcab026fcbb2..15e1463e5e13 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -137,7 +137,7 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
return 0;
}
-static struct resource __devinitdata tc6393xb_nand_resources[] = {
+static struct resource tc6393xb_nand_resources[] = {
{
.start = 0x1000,
.end = 0x1007,
@@ -196,7 +196,7 @@ static const struct resource tc6393xb_ohci_resources[] = {
},
};
-static struct resource __devinitdata tc6393xb_fb_resources[] = {
+static struct resource tc6393xb_fb_resources[] = {
{
.start = 0x5000,
.end = 0x51ff,
@@ -382,7 +382,7 @@ static struct tmio_mmc_data tc6393xb_mmc_data = {
.set_clk_div = tc6393xb_mmc_clk_div,
};
-static struct mfd_cell __devinitdata tc6393xb_cells[] = {
+static struct mfd_cell tc6393xb_cells[] = {
[TC6393XB_CELL_NAND] = {
.name = "tmio-nand",
.enable = tc6393xb_nand_enable,
@@ -602,7 +602,7 @@ static void tc6393xb_detach_irq(struct platform_device *dev)
/*--------------------------------------------------------------------------*/
-static int __devinit tc6393xb_probe(struct platform_device *dev)
+static int tc6393xb_probe(struct platform_device *dev)
{
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
struct tc6393xb *tc6393xb;
@@ -731,7 +731,7 @@ err_kzalloc:
return ret;
}
-static int __devexit tc6393xb_remove(struct platform_device *dev)
+static int tc6393xb_remove(struct platform_device *dev)
{
struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
@@ -831,7 +831,7 @@ static int tc6393xb_resume(struct platform_device *dev)
static struct platform_driver tc6393xb_driver = {
.probe = tc6393xb_probe,
- .remove = __devexit_p(tc6393xb_remove),
+ .remove = tc6393xb_remove,
.suspend = tc6393xb_suspend,
.resume = tc6393xb_resume,
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index 7c3675a74f93..09a14cec351b 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -315,7 +315,7 @@ static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
return IRQ_HANDLED;
}
-static int __devinit ti_ssp_probe(struct platform_device *pdev)
+static int ti_ssp_probe(struct platform_device *pdev)
{
static struct ti_ssp *ssp;
const struct ti_ssp_data *pdata = pdev->dev.platform_data;
@@ -433,7 +433,7 @@ error_res:
return error;
}
-static int __devexit ti_ssp_remove(struct platform_device *pdev)
+static int ti_ssp_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ti_ssp *ssp = dev_get_drvdata(dev);
@@ -451,7 +451,7 @@ static int __devexit ti_ssp_remove(struct platform_device *pdev)
static struct platform_driver ti_ssp_driver = {
.probe = ti_ssp_probe,
- .remove = __devexit_p(ti_ssp_remove),
+ .remove = ti_ssp_remove,
.driver = {
.name = "ti-ssp",
.owner = THIS_MODULE,
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index cccc626c83c8..59e0ee247e86 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -75,13 +75,13 @@ static struct i2c_board_info timberdale_i2c_board_info[] = {
},
};
-static __devinitdata struct xiic_i2c_platform_data
+static struct xiic_i2c_platform_data
timberdale_xiic_platform_data = {
.devices = timberdale_i2c_board_info,
.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
};
-static __devinitdata struct ocores_i2c_platform_data
+static struct ocores_i2c_platform_data
timberdale_ocores_platform_data = {
.reg_shift = 2,
.clock_khz = 62500,
@@ -89,7 +89,7 @@ timberdale_ocores_platform_data = {
.num_devices = ARRAY_SIZE(timberdale_i2c_board_info)
};
-static const __devinitconst struct resource timberdale_xiic_resources[] = {
+static const struct resource timberdale_xiic_resources[] = {
{
.start = XIICOFFSET,
.end = XIICEND,
@@ -102,7 +102,7 @@ static const __devinitconst struct resource timberdale_xiic_resources[] = {
},
};
-static const __devinitconst struct resource timberdale_ocores_resources[] = {
+static const struct resource timberdale_ocores_resources[] = {
{
.start = OCORESOFFSET,
.end = OCORESEND,
@@ -143,7 +143,7 @@ static struct spi_board_info timberdale_spi_8bit_board_info[] = {
},
};
-static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
+static struct xspi_platform_data timberdale_xspi_platform_data = {
.num_chipselect = 3,
.little_endian = true,
/* bits per word and devices will be filled in runtime depending
@@ -151,7 +151,7 @@ static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = {
*/
};
-static const __devinitconst struct resource timberdale_spi_resources[] = {
+static const struct resource timberdale_spi_resources[] = {
{
.start = SPIOFFSET,
.end = SPIEND,
@@ -164,13 +164,13 @@ static const __devinitconst struct resource timberdale_spi_resources[] = {
},
};
-static __devinitdata struct ks8842_platform_data
+static struct ks8842_platform_data
timberdale_ks8842_platform_data = {
.rx_dma_channel = DMA_ETH_RX,
.tx_dma_channel = DMA_ETH_TX
};
-static const __devinitconst struct resource timberdale_eth_resources[] = {
+static const struct resource timberdale_eth_resources[] = {
{
.start = ETHOFFSET,
.end = ETHEND,
@@ -183,14 +183,14 @@ static const __devinitconst struct resource timberdale_eth_resources[] = {
},
};
-static __devinitdata struct timbgpio_platform_data
+static struct timbgpio_platform_data
timberdale_gpio_platform_data = {
.gpio_base = 0,
.nr_pins = GPIO_NR_PINS,
.irq_base = 200,
};
-static const __devinitconst struct resource timberdale_gpio_resources[] = {
+static const struct resource timberdale_gpio_resources[] = {
{
.start = GPIOOFFSET,
.end = GPIOEND,
@@ -203,7 +203,7 @@ static const __devinitconst struct resource timberdale_gpio_resources[] = {
},
};
-static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
+static const struct resource timberdale_mlogicore_resources[] = {
{
.start = MLCOREOFFSET,
.end = MLCOREEND,
@@ -221,7 +221,7 @@ static const __devinitconst struct resource timberdale_mlogicore_resources[] = {
},
};
-static const __devinitconst struct resource timberdale_uart_resources[] = {
+static const struct resource timberdale_uart_resources[] = {
{
.start = UARTOFFSET,
.end = UARTEND,
@@ -234,7 +234,7 @@ static const __devinitconst struct resource timberdale_uart_resources[] = {
},
};
-static const __devinitconst struct resource timberdale_uartlite_resources[] = {
+static const struct resource timberdale_uartlite_resources[] = {
{
.start = UARTLITEOFFSET,
.end = UARTLITEEND,
@@ -247,13 +247,13 @@ static const __devinitconst struct resource timberdale_uartlite_resources[] = {
},
};
-static __devinitdata struct i2c_board_info timberdale_adv7180_i2c_board_info = {
+static struct i2c_board_info timberdale_adv7180_i2c_board_info = {
/* Requires jumper JP9 to be off */
I2C_BOARD_INFO("adv7180", 0x42 >> 1),
.irq = IRQ_TIMBERDALE_ADV7180
};
-static __devinitdata struct timb_video_platform_data
+static struct timb_video_platform_data
timberdale_video_platform_data = {
.dma_channel = DMA_VIDEO_RX,
.i2c_adapter = 0,
@@ -262,7 +262,7 @@ static __devinitdata struct timb_video_platform_data
}
};
-static const __devinitconst struct resource
+static const struct resource
timberdale_radio_resources[] = {
{
.start = RDSOFFSET,
@@ -276,22 +276,22 @@ timberdale_radio_resources[] = {
},
};
-static __devinitdata struct i2c_board_info timberdale_tef6868_i2c_board_info = {
+static struct i2c_board_info timberdale_tef6868_i2c_board_info = {
I2C_BOARD_INFO("tef6862", 0x60)
};
-static __devinitdata struct i2c_board_info timberdale_saa7706_i2c_board_info = {
+static struct i2c_board_info timberdale_saa7706_i2c_board_info = {
I2C_BOARD_INFO("saa7706h", 0x1C)
};
-static __devinitdata struct timb_radio_platform_data
+static struct timb_radio_platform_data
timberdale_radio_platform_data = {
.i2c_adapter = 0,
.tuner = &timberdale_tef6868_i2c_board_info,
.dsp = &timberdale_saa7706_i2c_board_info
};
-static const __devinitconst struct resource timberdale_video_resources[] = {
+static const struct resource timberdale_video_resources[] = {
{
.start = LOGIWOFFSET,
.end = LOGIWEND,
@@ -303,7 +303,7 @@ static const __devinitconst struct resource timberdale_video_resources[] = {
*/
};
-static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
+static struct timb_dma_platform_data timb_dma_platform_data = {
.nr_channels = 10,
.channels = {
{
@@ -362,7 +362,7 @@ static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = {
}
};
-static const __devinitconst struct resource timberdale_dma_resources[] = {
+static const struct resource timberdale_dma_resources[] = {
{
.start = DMAOFFSET,
.end = DMAEND,
@@ -375,7 +375,7 @@ static const __devinitconst struct resource timberdale_dma_resources[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -432,7 +432,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -499,7 +499,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -549,7 +549,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
{
.name = "timb-dma",
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -606,7 +606,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = {
},
};
-static const __devinitconst struct resource timberdale_sdhc_resources[] = {
+static const struct resource timberdale_sdhc_resources[] = {
/* located in bar 1 and bar 2 */
{
.start = SDHC0OFFSET,
@@ -620,7 +620,7 @@ static const __devinitconst struct resource timberdale_sdhc_resources[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
+static struct mfd_cell timberdale_cells_bar1[] = {
{
.name = "sdhci",
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -628,7 +628,7 @@ static __devinitdata struct mfd_cell timberdale_cells_bar1[] = {
},
};
-static __devinitdata struct mfd_cell timberdale_cells_bar2[] = {
+static struct mfd_cell timberdale_cells_bar2[] = {
{
.name = "sdhci",
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -650,7 +650,7 @@ static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
/*--------------------------------------------------------------------------*/
-static int __devinit timb_probe(struct pci_dev *dev,
+static int timb_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct timberdale_device *priv;
@@ -840,7 +840,7 @@ err_enable:
return -ENODEV;
}
-static void __devexit timb_remove(struct pci_dev *dev)
+static void timb_remove(struct pci_dev *dev)
{
struct timberdale_device *priv = pci_get_drvdata(dev);
@@ -867,7 +867,7 @@ static struct pci_driver timberdale_pci_driver = {
.name = DRIVER_NAME,
.id_table = timberdale_pci_tbl,
.probe = timb_probe,
- .remove = __devexit_p(timb_remove),
+ .remove = timb_remove,
};
static int __init timberdale_init(void)
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index 14051bdc714b..1d302f583adf 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -86,7 +86,7 @@ fail:
}
EXPORT_SYMBOL(tps6105x_mask_and_set);
-static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
+static int tps6105x_startup(struct tps6105x *tps6105x)
{
int ret;
u8 regval;
@@ -133,7 +133,7 @@ static struct mfd_cell tps6105x_cells[] = {
},
};
-static int __devinit tps6105x_probe(struct i2c_client *client,
+static int tps6105x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps6105x *tps6105x;
@@ -199,7 +199,7 @@ fail:
return ret;
}
-static int __devexit tps6105x_remove(struct i2c_client *client)
+static int tps6105x_remove(struct i2c_client *client)
{
struct tps6105x *tps6105x = i2c_get_clientdata(client);
@@ -226,7 +226,7 @@ static struct i2c_driver tps6105x_driver = {
.name = "tps6105x",
},
.probe = tps6105x_probe,
- .remove = __devexit_p(tps6105x_remove),
+ .remove = tps6105x_remove,
.id_table = tps6105x_id,
};
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index 074ae32b0d2a..382a857b0dde 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -188,7 +188,7 @@ static irqreturn_t tps65090_irq(int irq, void *data)
return acks ? IRQ_HANDLED : IRQ_NONE;
}
-static int __devinit tps65090_irq_init(struct tps65090 *tps65090, int irq,
+static int tps65090_irq_init(struct tps65090 *tps65090, int irq,
int irq_base)
{
int i, ret;
@@ -251,7 +251,7 @@ static const struct regmap_config tps65090_regmap_config = {
.volatile_reg = is_volatile_reg,
};
-static int __devinit tps65090_i2c_probe(struct i2c_client *client,
+static int tps65090_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps65090_platform_data *pdata = client->dev.platform_data;
@@ -308,7 +308,7 @@ err_exit:
return ret;
}
-static int __devexit tps65090_i2c_remove(struct i2c_client *client)
+static int tps65090_i2c_remove(struct i2c_client *client)
{
struct tps65090 *tps65090 = i2c_get_clientdata(client);
@@ -354,7 +354,7 @@ static struct i2c_driver tps65090_driver = {
.pm = &tps65090_pm_ops,
},
.probe = tps65090_i2c_probe,
- .remove = __devexit_p(tps65090_i2c_remove),
+ .remove = tps65090_i2c_remove,
.id_table = tps65090_id_table,
};
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 3fb32e655254..e14e252e3473 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -153,7 +153,7 @@ static const struct of_device_id tps65217_of_match[] = {
{ /* sentinel */ },
};
-static int __devinit tps65217_probe(struct i2c_client *client,
+static int tps65217_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct tps65217 *tps;
@@ -214,7 +214,7 @@ static int __devinit tps65217_probe(struct i2c_client *client,
return 0;
}
-static int __devexit tps65217_remove(struct i2c_client *client)
+static int tps65217_remove(struct i2c_client *client)
{
struct tps65217 *tps = i2c_get_clientdata(client);
@@ -237,7 +237,7 @@ static struct i2c_driver tps65217_driver = {
},
.id_table = tps65217_id_table,
.probe = tps65217_probe,
- .remove = __devexit_p(tps65217_remove),
+ .remove = tps65217_remove,
};
static int __init tps65217_init(void)
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 467464368773..9f92c3b22093 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -267,7 +267,7 @@ static irqreturn_t tps6586x_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
+static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
int irq_base)
{
int i, ret;
@@ -316,7 +316,7 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
return ret;
}
-static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
+static int tps6586x_add_subdevs(struct tps6586x *tps6586x,
struct tps6586x_platform_data *pdata)
{
struct tps6586x_subdev_info *subdev;
@@ -468,7 +468,7 @@ static void tps6586x_power_off(void)
tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
}
-static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
+static int tps6586x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps6586x_platform_data *pdata = client->dev.platform_data;
@@ -548,7 +548,7 @@ err_mfd_add:
return ret;
}
-static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
+static int tps6586x_i2c_remove(struct i2c_client *client)
{
struct tps6586x *tps6586x = i2c_get_clientdata(client);
@@ -572,7 +572,7 @@ static struct i2c_driver tps6586x_driver = {
.of_match_table = of_match_ptr(tps6586x_of_match),
},
.probe = tps6586x_i2c_probe,
- .remove = __devexit_p(tps6586x_i2c_remove),
+ .remove = tps6586x_i2c_remove,
.id_table = tps6586x_id_table,
};
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 0d79ce2b5014..ce054654f5bb 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -78,7 +78,7 @@ static const struct regmap_config tps65910_regmap_config = {
.cache_type = REGCACHE_RBTREE,
};
-static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
+static int tps65910_ck32k_init(struct tps65910 *tps65910,
struct tps65910_board *pmic_pdata)
{
int ret;
@@ -96,7 +96,7 @@ static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910,
return 0;
}
-static int __devinit tps65910_sleepinit(struct tps65910 *tps65910,
+static int tps65910_sleepinit(struct tps65910 *tps65910,
struct tps65910_board *pmic_pdata)
{
struct device *dev = NULL;
@@ -237,7 +237,7 @@ static void tps65910_power_off(void)
DEVCTRL_DEV_ON_MASK);
}
-static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
+static int tps65910_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tps65910 *tps65910;
@@ -302,7 +302,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
return ret;
}
-static __devexit int tps65910_i2c_remove(struct i2c_client *i2c)
+static int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
@@ -327,7 +327,7 @@ static struct i2c_driver tps65910_i2c_driver = {
.of_match_table = of_match_ptr(tps65910_of_match),
},
.probe = tps65910_i2c_probe,
- .remove = __devexit_p(tps65910_i2c_remove),
+ .remove = tps65910_i2c_remove,
.id_table = tps65910_i2c_id,
};
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index 0b6e361432c4..c0816ebd9d7e 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -122,7 +122,7 @@ static ssize_t comp_threshold_show(struct device *dev,
static DEVICE_ATTR(comp1_threshold, S_IRUGO, comp_threshold_show, NULL);
static DEVICE_ATTR(comp2_threshold, S_IRUGO, comp_threshold_show, NULL);
-static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
+static int tps65911_comparator_probe(struct platform_device *pdev)
{
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
@@ -152,7 +152,7 @@ static __devinit int tps65911_comparator_probe(struct platform_device *pdev)
return ret;
}
-static __devexit int tps65911_comparator_remove(struct platform_device *pdev)
+static int tps65911_comparator_remove(struct platform_device *pdev)
{
struct tps65910 *tps65910;
@@ -169,7 +169,7 @@ static struct platform_driver tps65911_comparator_driver = {
.owner = THIS_MODULE,
},
.probe = tps65911_comparator_probe,
- .remove = __devexit_p(tps65911_comparator_remove),
+ .remove = tps65911_comparator_remove,
};
static int __init tps65911_comparator_init(void)
diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c
index 27d3302d56b8..b45f460d299f 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -81,7 +81,7 @@ static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr,
return ret;
}
-static int __devinit tps65912_spi_probe(struct spi_device *spi)
+static int tps65912_spi_probe(struct spi_device *spi)
{
struct tps65912 *tps65912;
@@ -99,7 +99,7 @@ static int __devinit tps65912_spi_probe(struct spi_device *spi)
return tps65912_device_init(tps65912);
}
-static int __devexit tps65912_spi_remove(struct spi_device *spi)
+static int tps65912_spi_remove(struct spi_device *spi)
{
struct tps65912 *tps65912 = spi_get_drvdata(spi);
@@ -114,7 +114,7 @@ static struct spi_driver tps65912_spi_driver = {
.owner = THIS_MODULE,
},
.probe = tps65912_spi_probe,
- .remove = __devexit_p(tps65912_spi_remove),
+ .remove = tps65912_spi_remove,
};
static int __init tps65912_spi_init(void)
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 4ae642320205..11b76c0109f5 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -671,7 +671,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
}
if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
- child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+ child = add_child(SUB_CHIP_ID1, "twl6030-pwm", NULL, 0,
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
@@ -1170,7 +1170,7 @@ static int twl_remove(struct i2c_client *client)
}
/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
-static int __devinit
+static int
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct twl4030_platform_data *pdata = client->dev.platform_data;
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index 5c11acf9e0fd..e16edca92670 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -184,7 +184,7 @@ static bool twl4030_audio_has_vibra(struct twl4030_audio_data *pdata,
return false;
}
-static int __devinit twl4030_audio_probe(struct platform_device *pdev)
+static int twl4030_audio_probe(struct platform_device *pdev)
{
struct twl4030_audio *audio;
struct twl4030_audio_data *pdata = pdev->dev.platform_data;
@@ -269,7 +269,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit twl4030_audio_remove(struct platform_device *pdev)
+static int twl4030_audio_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
platform_set_drvdata(pdev, NULL);
@@ -291,7 +291,7 @@ static struct platform_driver twl4030_audio_driver = {
.of_match_table = twl4030_audio_of_match,
},
.probe = twl4030_audio_probe,
- .remove = __devexit_p(twl4030_audio_remove),
+ .remove = twl4030_audio_remove,
};
module_platform_driver(twl4030_audio_driver);
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index ad733d76207a..cdd1173ed4e9 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
irq = sih_mod + twl4030_irq_base;
irq_set_handler_data(irq, agent);
agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
- status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
+ status = request_threaded_irq(irq, NULL, handle_twl4030_sih,
+ IRQF_EARLY_RESUME,
agent->irq_name ?: sih->name, NULL);
dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 456ecb5ac4fe..a39dcf3e2133 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -692,7 +692,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
/*
* Initialize MADC and request for threaded irq
*/
-static int __devinit twl4030_madc_probe(struct platform_device *pdev)
+static int twl4030_madc_probe(struct platform_device *pdev)
{
struct twl4030_madc_data *madc;
struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
@@ -785,7 +785,7 @@ err_power:
return ret;
}
-static int __devexit twl4030_madc_remove(struct platform_device *pdev)
+static int twl4030_madc_remove(struct platform_device *pdev)
{
struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 79ca33dfacca..a5332063183a 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -124,7 +124,7 @@ static u8 res_config_addrs[] = {
[RES_MAIN_REF] = 0x94,
};
-static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
+static int twl4030_write_script_byte(u8 address, u8 byte)
{
int err;
@@ -138,7 +138,7 @@ out:
return err;
}
-static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,
+static int twl4030_write_script_ins(u8 address, u16 pmb_message,
u8 delay, u8 next)
{
int err;
@@ -158,7 +158,7 @@ out:
return err;
}
-static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,
+static int twl4030_write_script(u8 address, struct twl4030_ins *script,
int len)
{
int err;
@@ -183,7 +183,7 @@ static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script
return err;
}
-static int __devinit twl4030_config_wakeup3_sequence(u8 address)
+static int twl4030_config_wakeup3_sequence(u8 address)
{
int err;
u8 data;
@@ -208,7 +208,7 @@ out:
return err;
}
-static int __devinit twl4030_config_wakeup12_sequence(u8 address)
+static int twl4030_config_wakeup12_sequence(u8 address)
{
int err = 0;
u8 data;
@@ -262,7 +262,7 @@ out:
return err;
}
-static int __devinit twl4030_config_sleep_sequence(u8 address)
+static int twl4030_config_sleep_sequence(u8 address)
{
int err;
@@ -276,7 +276,7 @@ static int __devinit twl4030_config_sleep_sequence(u8 address)
return err;
}
-static int __devinit twl4030_config_warmreset_sequence(u8 address)
+static int twl4030_config_warmreset_sequence(u8 address)
{
int err;
u8 rd_data;
@@ -324,7 +324,7 @@ out:
return err;
}
-static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)
+static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
{
int rconfig_addr;
int err;
@@ -416,7 +416,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
return 0;
}
-static int __devinit load_twl4030_script(struct twl4030_script *tscript,
+static int load_twl4030_script(struct twl4030_script *tscript,
u8 address)
{
int err;
@@ -527,7 +527,7 @@ void twl4030_power_off(void)
pr_err("TWL4030 Unable to power off\n");
}
-void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
+void twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
int i;
diff --git a/drivers/mfd/vx855.c b/drivers/mfd/vx855.c
index b9a636d44c7f..757ecc63338c 100644
--- a/drivers/mfd/vx855.c
+++ b/drivers/mfd/vx855.c
@@ -72,7 +72,7 @@ static struct mfd_cell vx855_cells[] = {
},
};
-static __devinit int vx855_probe(struct pci_dev *pdev,
+static int vx855_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
@@ -112,7 +112,7 @@ out:
return ret;
}
-static void __devexit vx855_remove(struct pci_dev *pdev)
+static void vx855_remove(struct pci_dev *pdev)
{
mfd_remove_devices(&pdev->dev);
pci_disable_device(pdev);
@@ -128,7 +128,7 @@ static struct pci_driver vx855_pci_driver = {
.name = "vx855",
.id_table = vx855_pci_tbl,
.probe = vx855_probe,
- .remove = __devexit_p(vx855_remove),
+ .remove = vx855_remove,
};
module_pci_driver(vx855_pci_driver);
diff --git a/drivers/mfd/wl1273-core.c b/drivers/mfd/wl1273-core.c
index 86e0e4309fc2..edbe6c1b755a 100644
--- a/drivers/mfd/wl1273-core.c
+++ b/drivers/mfd/wl1273-core.c
@@ -182,7 +182,7 @@ static int wl1273_core_remove(struct i2c_client *client)
return 0;
}
-static int __devinit wl1273_core_probe(struct i2c_client *client,
+static int wl1273_core_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct wl1273_fm_platform_data *pdata = client->dev.platform_data;
@@ -262,7 +262,7 @@ static struct i2c_driver wl1273_core_driver = {
},
.probe = wl1273_core_probe,
.id_table = wl1273_driver_id_table,
- .remove = __devexit_p(wl1273_core_remove),
+ .remove = wl1273_core_remove,
};
static int __init wl1273_core_init(void)
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 01b9255ed631..14490cc785d2 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -43,6 +43,7 @@ static const struct reg_default wm5102_reva_patch[] = {
{ 0x479, 0x0A30 },
{ 0x47B, 0x0810 },
{ 0x47D, 0x0510 },
+ { 0x4D1, 0x017F },
{ 0x500, 0x000D },
{ 0x507, 0x1820 },
{ 0x508, 0x1820 },
@@ -52,524 +53,6 @@ static const struct reg_default wm5102_reva_patch[] = {
{ 0x580, 0x000D },
{ 0x587, 0x1820 },
{ 0x588, 0x1820 },
- { 0x101, 0x8140 },
- { 0x3000, 0x2225 },
- { 0x3001, 0x3a03 },
- { 0x3002, 0x0225 },
- { 0x3003, 0x0801 },
- { 0x3004, 0x6249 },
- { 0x3005, 0x0c04 },
- { 0x3006, 0x0225 },
- { 0x3007, 0x5901 },
- { 0x3008, 0xe249 },
- { 0x3009, 0x030d },
- { 0x300a, 0x0249 },
- { 0x300b, 0x2c01 },
- { 0x300c, 0xe249 },
- { 0x300d, 0x4342 },
- { 0x300e, 0xe249 },
- { 0x300f, 0x73c0 },
- { 0x3010, 0x4249 },
- { 0x3011, 0x0c00 },
- { 0x3012, 0x0225 },
- { 0x3013, 0x1f01 },
- { 0x3014, 0x0225 },
- { 0x3015, 0x1e01 },
- { 0x3016, 0x0225 },
- { 0x3017, 0xfa00 },
- { 0x3018, 0x0000 },
- { 0x3019, 0xf000 },
- { 0x301a, 0x0000 },
- { 0x301b, 0xf000 },
- { 0x301c, 0x0000 },
- { 0x301d, 0xf000 },
- { 0x301e, 0x0000 },
- { 0x301f, 0xf000 },
- { 0x3020, 0x0000 },
- { 0x3021, 0xf000 },
- { 0x3022, 0x0000 },
- { 0x3023, 0xf000 },
- { 0x3024, 0x0000 },
- { 0x3025, 0xf000 },
- { 0x3026, 0x0000 },
- { 0x3027, 0xf000 },
- { 0x3028, 0x0000 },
- { 0x3029, 0xf000 },
- { 0x302a, 0x0000 },
- { 0x302b, 0xf000 },
- { 0x302c, 0x0000 },
- { 0x302d, 0xf000 },
- { 0x302e, 0x0000 },
- { 0x302f, 0xf000 },
- { 0x3030, 0x0225 },
- { 0x3031, 0x1a01 },
- { 0x3032, 0x0225 },
- { 0x3033, 0x1e00 },
- { 0x3034, 0x0225 },
- { 0x3035, 0x1f00 },
- { 0x3036, 0x6225 },
- { 0x3037, 0xf800 },
- { 0x3038, 0x0000 },
- { 0x3039, 0xf000 },
- { 0x303a, 0x0000 },
- { 0x303b, 0xf000 },
- { 0x303c, 0x0000 },
- { 0x303d, 0xf000 },
- { 0x303e, 0x0000 },
- { 0x303f, 0xf000 },
- { 0x3040, 0x2226 },
- { 0x3041, 0x3a03 },
- { 0x3042, 0x0226 },
- { 0x3043, 0x0801 },
- { 0x3044, 0x6249 },
- { 0x3045, 0x0c06 },
- { 0x3046, 0x0226 },
- { 0x3047, 0x5901 },
- { 0x3048, 0xe249 },
- { 0x3049, 0x030d },
- { 0x304a, 0x0249 },
- { 0x304b, 0x2c01 },
- { 0x304c, 0xe249 },
- { 0x304d, 0x4342 },
- { 0x304e, 0xe249 },
- { 0x304f, 0x73c0 },
- { 0x3050, 0x4249 },
- { 0x3051, 0x0c00 },
- { 0x3052, 0x0226 },
- { 0x3053, 0x1f01 },
- { 0x3054, 0x0226 },
- { 0x3055, 0x1e01 },
- { 0x3056, 0x0226 },
- { 0x3057, 0xfa00 },
- { 0x3058, 0x0000 },
- { 0x3059, 0xf000 },
- { 0x305a, 0x0000 },
- { 0x305b, 0xf000 },
- { 0x305c, 0x0000 },
- { 0x305d, 0xf000 },
- { 0x305e, 0x0000 },
- { 0x305f, 0xf000 },
- { 0x3060, 0x0000 },
- { 0x3061, 0xf000 },
- { 0x3062, 0x0000 },
- { 0x3063, 0xf000 },
- { 0x3064, 0x0000 },
- { 0x3065, 0xf000 },
- { 0x3066, 0x0000 },
- { 0x3067, 0xf000 },
- { 0x3068, 0x0000 },
- { 0x3069, 0xf000 },
- { 0x306a, 0x0000 },
- { 0x306b, 0xf000 },
- { 0x306c, 0x0000 },
- { 0x306d, 0xf000 },
- { 0x306e, 0x0000 },
- { 0x306f, 0xf000 },
- { 0x3070, 0x0226 },
- { 0x3071, 0x1a01 },
- { 0x3072, 0x0226 },
- { 0x3073, 0x1e00 },
- { 0x3074, 0x0226 },
- { 0x3075, 0x1f00 },
- { 0x3076, 0x6226 },
- { 0x3077, 0xf800 },
- { 0x3078, 0x0000 },
- { 0x3079, 0xf000 },
- { 0x307a, 0x0000 },
- { 0x307b, 0xf000 },
- { 0x307c, 0x0000 },
- { 0x307d, 0xf000 },
- { 0x307e, 0x0000 },
- { 0x307f, 0xf000 },
- { 0x3080, 0x2227 },
- { 0x3081, 0x3a03 },
- { 0x3082, 0x0227 },
- { 0x3083, 0x0801 },
- { 0x3084, 0x6255 },
- { 0x3085, 0x0c04 },
- { 0x3086, 0x0227 },
- { 0x3087, 0x5901 },
- { 0x3088, 0xe255 },
- { 0x3089, 0x030d },
- { 0x308a, 0x0255 },
- { 0x308b, 0x2c01 },
- { 0x308c, 0xe255 },
- { 0x308d, 0x4342 },
- { 0x308e, 0xe255 },
- { 0x308f, 0x73c0 },
- { 0x3090, 0x4255 },
- { 0x3091, 0x0c00 },
- { 0x3092, 0x0227 },
- { 0x3093, 0x1f01 },
- { 0x3094, 0x0227 },
- { 0x3095, 0x1e01 },
- { 0x3096, 0x0227 },
- { 0x3097, 0xfa00 },
- { 0x3098, 0x0000 },
- { 0x3099, 0xf000 },
- { 0x309a, 0x0000 },
- { 0x309b, 0xf000 },
- { 0x309c, 0x0000 },
- { 0x309d, 0xf000 },
- { 0x309e, 0x0000 },
- { 0x309f, 0xf000 },
- { 0x30a0, 0x0000 },
- { 0x30a1, 0xf000 },
- { 0x30a2, 0x0000 },
- { 0x30a3, 0xf000 },
- { 0x30a4, 0x0000 },
- { 0x30a5, 0xf000 },
- { 0x30a6, 0x0000 },
- { 0x30a7, 0xf000 },
- { 0x30a8, 0x0000 },
- { 0x30a9, 0xf000 },
- { 0x30aa, 0x0000 },
- { 0x30ab, 0xf000 },
- { 0x30ac, 0x0000 },
- { 0x30ad, 0xf000 },
- { 0x30ae, 0x0000 },
- { 0x30af, 0xf000 },
- { 0x30b0, 0x0227 },
- { 0x30b1, 0x1a01 },
- { 0x30b2, 0x0227 },
- { 0x30b3, 0x1e00 },
- { 0x30b4, 0x0227 },
- { 0x30b5, 0x1f00 },
- { 0x30b6, 0x6227 },
- { 0x30b7, 0xf800 },
- { 0x30b8, 0x0000 },
- { 0x30b9, 0xf000 },
- { 0x30ba, 0x0000 },
- { 0x30bb, 0xf000 },
- { 0x30bc, 0x0000 },
- { 0x30bd, 0xf000 },
- { 0x30be, 0x0000 },
- { 0x30bf, 0xf000 },
- { 0x30c0, 0x2228 },
- { 0x30c1, 0x3a03 },
- { 0x30c2, 0x0228 },
- { 0x30c3, 0x0801 },
- { 0x30c4, 0x6255 },
- { 0x30c5, 0x0c06 },
- { 0x30c6, 0x0228 },
- { 0x30c7, 0x5901 },
- { 0x30c8, 0xe255 },
- { 0x30c9, 0x030d },
- { 0x30ca, 0x0255 },
- { 0x30cb, 0x2c01 },
- { 0x30cc, 0xe255 },
- { 0x30cd, 0x4342 },
- { 0x30ce, 0xe255 },
- { 0x30cf, 0x73c0 },
- { 0x30d0, 0x4255 },
- { 0x30d1, 0x0c00 },
- { 0x30d2, 0x0228 },
- { 0x30d3, 0x1f01 },
- { 0x30d4, 0x0228 },
- { 0x30d5, 0x1e01 },
- { 0x30d6, 0x0228 },
- { 0x30d7, 0xfa00 },
- { 0x30d8, 0x0000 },
- { 0x30d9, 0xf000 },
- { 0x30da, 0x0000 },
- { 0x30db, 0xf000 },
- { 0x30dc, 0x0000 },
- { 0x30dd, 0xf000 },
- { 0x30de, 0x0000 },
- { 0x30df, 0xf000 },
- { 0x30e0, 0x0000 },
- { 0x30e1, 0xf000 },
- { 0x30e2, 0x0000 },
- { 0x30e3, 0xf000 },
- { 0x30e4, 0x0000 },
- { 0x30e5, 0xf000 },
- { 0x30e6, 0x0000 },
- { 0x30e7, 0xf000 },
- { 0x30e8, 0x0000 },
- { 0x30e9, 0xf000 },
- { 0x30ea, 0x0000 },
- { 0x30eb, 0xf000 },
- { 0x30ec, 0x0000 },
- { 0x30ed, 0xf000 },
- { 0x30ee, 0x0000 },
- { 0x30ef, 0xf000 },
- { 0x30f0, 0x0228 },
- { 0x30f1, 0x1a01 },
- { 0x30f2, 0x0228 },
- { 0x30f3, 0x1e00 },
- { 0x30f4, 0x0228 },
- { 0x30f5, 0x1f00 },
- { 0x30f6, 0x6228 },
- { 0x30f7, 0xf800 },
- { 0x30f8, 0x0000 },
- { 0x30f9, 0xf000 },
- { 0x30fa, 0x0000 },
- { 0x30fb, 0xf000 },
- { 0x30fc, 0x0000 },
- { 0x30fd, 0xf000 },
- { 0x30fe, 0x0000 },
- { 0x30ff, 0xf000 },
- { 0x3100, 0x222b },
- { 0x3101, 0x3a03 },
- { 0x3102, 0x222b },
- { 0x3103, 0x5803 },
- { 0x3104, 0xe26f },
- { 0x3105, 0x030d },
- { 0x3106, 0x626f },
- { 0x3107, 0x2c01 },
- { 0x3108, 0xe26f },
- { 0x3109, 0x4342 },
- { 0x310a, 0xe26f },
- { 0x310b, 0x73c0 },
- { 0x310c, 0x026f },
- { 0x310d, 0x0c00 },
- { 0x310e, 0x022b },
- { 0x310f, 0x1f01 },
- { 0x3110, 0x022b },
- { 0x3111, 0x1e01 },
- { 0x3112, 0x022b },
- { 0x3113, 0xfa00 },
- { 0x3114, 0x0000 },
- { 0x3115, 0xf000 },
- { 0x3116, 0x0000 },
- { 0x3117, 0xf000 },
- { 0x3118, 0x0000 },
- { 0x3119, 0xf000 },
- { 0x311a, 0x0000 },
- { 0x311b, 0xf000 },
- { 0x311c, 0x0000 },
- { 0x311d, 0xf000 },
- { 0x311e, 0x0000 },
- { 0x311f, 0xf000 },
- { 0x3120, 0x022b },
- { 0x3121, 0x0a01 },
- { 0x3122, 0x022b },
- { 0x3123, 0x1e00 },
- { 0x3124, 0x022b },
- { 0x3125, 0x1f00 },
- { 0x3126, 0x622b },
- { 0x3127, 0xf800 },
- { 0x3128, 0x0000 },
- { 0x3129, 0xf000 },
- { 0x312a, 0x0000 },
- { 0x312b, 0xf000 },
- { 0x312c, 0x0000 },
- { 0x312d, 0xf000 },
- { 0x312e, 0x0000 },
- { 0x312f, 0xf000 },
- { 0x3130, 0x0000 },
- { 0x3131, 0xf000 },
- { 0x3132, 0x0000 },
- { 0x3133, 0xf000 },
- { 0x3134, 0x0000 },
- { 0x3135, 0xf000 },
- { 0x3136, 0x0000 },
- { 0x3137, 0xf000 },
- { 0x3138, 0x0000 },
- { 0x3139, 0xf000 },
- { 0x313a, 0x0000 },
- { 0x313b, 0xf000 },
- { 0x313c, 0x0000 },
- { 0x313d, 0xf000 },
- { 0x313e, 0x0000 },
- { 0x313f, 0xf000 },
- { 0x3140, 0x0000 },
- { 0x3141, 0xf000 },
- { 0x3142, 0x0000 },
- { 0x3143, 0xf000 },
- { 0x3144, 0x0000 },
- { 0x3145, 0xf000 },
- { 0x3146, 0x0000 },
- { 0x3147, 0xf000 },
- { 0x3148, 0x0000 },
- { 0x3149, 0xf000 },
- { 0x314a, 0x0000 },
- { 0x314b, 0xf000 },
- { 0x314c, 0x0000 },
- { 0x314d, 0xf000 },
- { 0x314e, 0x0000 },
- { 0x314f, 0xf000 },
- { 0x3150, 0x0000 },
- { 0x3151, 0xf000 },
- { 0x3152, 0x0000 },
- { 0x3153, 0xf000 },
- { 0x3154, 0x0000 },
- { 0x3155, 0xf000 },
- { 0x3156, 0x0000 },
- { 0x3157, 0xf000 },
- { 0x3158, 0x0000 },
- { 0x3159, 0xf000 },
- { 0x315a, 0x0000 },
- { 0x315b, 0xf000 },
- { 0x315c, 0x0000 },
- { 0x315d, 0xf000 },
- { 0x315e, 0x0000 },
- { 0x315f, 0xf000 },
- { 0x3160, 0x0000 },
- { 0x3161, 0xf000 },
- { 0x3162, 0x0000 },
- { 0x3163, 0xf000 },
- { 0x3164, 0x0000 },
- { 0x3165, 0xf000 },
- { 0x3166, 0x0000 },
- { 0x3167, 0xf000 },
- { 0x3168, 0x0000 },
- { 0x3169, 0xf000 },
- { 0x316a, 0x0000 },
- { 0x316b, 0xf000 },
- { 0x316c, 0x0000 },
- { 0x316d, 0xf000 },
- { 0x316e, 0x0000 },
- { 0x316f, 0xf000 },
- { 0x3170, 0x0000 },
- { 0x3171, 0xf000 },
- { 0x3172, 0x0000 },
- { 0x3173, 0xf000 },
- { 0x3174, 0x0000 },
- { 0x3175, 0xf000 },
- { 0x3176, 0x0000 },
- { 0x3177, 0xf000 },
- { 0x3178, 0x0000 },
- { 0x3179, 0xf000 },
- { 0x317a, 0x0000 },
- { 0x317b, 0xf000 },
- { 0x317c, 0x0000 },
- { 0x317d, 0xf000 },
- { 0x317e, 0x0000 },
- { 0x317f, 0xf000 },
- { 0x3180, 0x2001 },
- { 0x3181, 0xf101 },
- { 0x3182, 0x0000 },
- { 0x3183, 0xf000 },
- { 0x3184, 0x0000 },
- { 0x3185, 0xf000 },
- { 0x3186, 0x0000 },
- { 0x3187, 0xf000 },
- { 0x3188, 0x0000 },
- { 0x3189, 0xf000 },
- { 0x318a, 0x0000 },
- { 0x318b, 0xf000 },
- { 0x318c, 0x0000 },
- { 0x318d, 0xf000 },
- { 0x318e, 0x0000 },
- { 0x318f, 0xf000 },
- { 0x3190, 0x0000 },
- { 0x3191, 0xf000 },
- { 0x3192, 0x0000 },
- { 0x3193, 0xf000 },
- { 0x3194, 0x0000 },
- { 0x3195, 0xf000 },
- { 0x3196, 0x0000 },
- { 0x3197, 0xf000 },
- { 0x3198, 0x0000 },
- { 0x3199, 0xf000 },
- { 0x319a, 0x0000 },
- { 0x319b, 0xf000 },
- { 0x319c, 0x0000 },
- { 0x319d, 0xf000 },
- { 0x319e, 0x0000 },
- { 0x319f, 0xf000 },
- { 0x31a0, 0x0000 },
- { 0x31a1, 0xf000 },
- { 0x31a2, 0x0000 },
- { 0x31a3, 0xf000 },
- { 0x31a4, 0x0000 },
- { 0x31a5, 0xf000 },
- { 0x31a6, 0x0000 },
- { 0x31a7, 0xf000 },
- { 0x31a8, 0x0000 },
- { 0x31a9, 0xf000 },
- { 0x31aa, 0x0000 },
- { 0x31ab, 0xf000 },
- { 0x31ac, 0x0000 },
- { 0x31ad, 0xf000 },
- { 0x31ae, 0x0000 },
- { 0x31af, 0xf000 },
- { 0x31b0, 0x0000 },
- { 0x31b1, 0xf000 },
- { 0x31b2, 0x0000 },
- { 0x31b3, 0xf000 },
- { 0x31b4, 0x0000 },
- { 0x31b5, 0xf000 },
- { 0x31b6, 0x0000 },
- { 0x31b7, 0xf000 },
- { 0x31b8, 0x0000 },
- { 0x31b9, 0xf000 },
- { 0x31ba, 0x0000 },
- { 0x31bb, 0xf000 },
- { 0x31bc, 0x0000 },
- { 0x31bd, 0xf000 },
- { 0x31be, 0x0000 },
- { 0x31bf, 0xf000 },
- { 0x31c0, 0x0000 },
- { 0x31c1, 0xf000 },
- { 0x31c2, 0x0000 },
- { 0x31c3, 0xf000 },
- { 0x31c4, 0x0000 },
- { 0x31c5, 0xf000 },
- { 0x31c6, 0x0000 },
- { 0x31c7, 0xf000 },
- { 0x31c8, 0x0000 },
- { 0x31c9, 0xf000 },
- { 0x31ca, 0x0000 },
- { 0x31cb, 0xf000 },
- { 0x31cc, 0x0000 },
- { 0x31cd, 0xf000 },
- { 0x31ce, 0x0000 },
- { 0x31cf, 0xf000 },
- { 0x31d0, 0x0000 },
- { 0x31d1, 0xf000 },
- { 0x31d2, 0x0000 },
- { 0x31d3, 0xf000 },
- { 0x31d4, 0x0000 },
- { 0x31d5, 0xf000 },
- { 0x31d6, 0x0000 },
- { 0x31d7, 0xf000 },
- { 0x31d8, 0x0000 },
- { 0x31d9, 0xf000 },
- { 0x31da, 0x0000 },
- { 0x31db, 0xf000 },
- { 0x31dc, 0x0000 },
- { 0x31dd, 0xf000 },
- { 0x31de, 0x0000 },
- { 0x31df, 0xf000 },
- { 0x31e0, 0x0000 },
- { 0x31e1, 0xf000 },
- { 0x31e2, 0x0000 },
- { 0x31e3, 0xf000 },
- { 0x31e4, 0x0000 },
- { 0x31e5, 0xf000 },
- { 0x31e6, 0x0000 },
- { 0x31e7, 0xf000 },
- { 0x31e8, 0x0000 },
- { 0x31e9, 0xf000 },
- { 0x31ea, 0x0000 },
- { 0x31eb, 0xf000 },
- { 0x31ec, 0x0000 },
- { 0x31ed, 0xf000 },
- { 0x31ee, 0x0000 },
- { 0x31ef, 0xf000 },
- { 0x31f0, 0x0000 },
- { 0x31f1, 0xf000 },
- { 0x31f2, 0x0000 },
- { 0x31f3, 0xf000 },
- { 0x31f4, 0x0000 },
- { 0x31f5, 0xf000 },
- { 0x31f6, 0x0000 },
- { 0x31f7, 0xf000 },
- { 0x31f8, 0x0000 },
- { 0x31f9, 0xf000 },
- { 0x31fa, 0x0000 },
- { 0x31fb, 0xf000 },
- { 0x31fc, 0x0000 },
- { 0x31fd, 0xf000 },
- { 0x31fe, 0x0000 },
- { 0x31ff, 0xf000 },
- { 0x024d, 0xff50 },
- { 0x0252, 0xff50 },
- { 0x0259, 0x0112 },
- { 0x025e, 0x0112 },
- { 0x101, 0x0304 },
{ 0x80, 0x0000 },
};
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index 4bceee98f0a4..4e70e157a909 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -21,7 +21,7 @@
#include <linux/mfd/wm831x/core.h>
-static int __devinit wm831x_spi_probe(struct spi_device *spi)
+static int wm831x_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct wm831x *wm831x;
@@ -51,7 +51,7 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
return wm831x_device_init(wm831x, type, spi->irq);
}
-static int __devexit wm831x_spi_remove(struct spi_device *spi)
+static int wm831x_spi_remove(struct spi_device *spi)
{
struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
@@ -99,7 +99,7 @@ static struct spi_driver wm831x_spi_driver = {
},
.id_table = wm831x_spi_ids,
.probe = wm831x_spi_probe,
- .remove = __devexit_p(wm831x_spi_remove),
+ .remove = wm831x_spi_remove,
.shutdown = wm831x_spi_shutdown,
};
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 8fefc961ec06..c7f62ac544ad 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -374,21 +374,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
-static const __devinitconst struct reg_default wm8994_revc_patch[] = {
+static const struct reg_default wm8994_revc_patch[] = {
{ 0x102, 0x3 },
{ 0x56, 0x3 },
{ 0x817, 0x0 },
{ 0x102, 0x0 },
};
-static const __devinitconst struct reg_default wm8958_reva_patch[] = {
+static const struct reg_default wm8958_reva_patch[] = {
{ 0x102, 0x3 },
{ 0xcb, 0x81 },
{ 0x817, 0x0 },
{ 0x102, 0x0 },
};
-static const __devinitconst struct reg_default wm1811_reva_patch[] = {
+static const struct reg_default wm1811_reva_patch[] = {
{ 0x102, 0x3 },
{ 0x56, 0xc07 },
{ 0x5d, 0x7e },
@@ -399,7 +399,7 @@ static const __devinitconst struct reg_default wm1811_reva_patch[] = {
/*
* Instantiate the generic non-control parts of the device.
*/
-static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
+static int wm8994_device_init(struct wm8994 *wm8994, int irq)
{
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
struct regmap_config *regmap_config;
@@ -671,7 +671,7 @@ err:
return ret;
}
-static __devexit void wm8994_device_exit(struct wm8994 *wm8994)
+static void wm8994_device_exit(struct wm8994 *wm8994)
{
pm_runtime_disable(wm8994->dev);
mfd_remove_devices(wm8994->dev);
@@ -689,7 +689,7 @@ static const struct of_device_id wm8994_of_match[] = {
};
MODULE_DEVICE_TABLE(of, wm8994_of_match);
-static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
+static int wm8994_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
@@ -715,7 +715,7 @@ static __devinit int wm8994_i2c_probe(struct i2c_client *i2c,
return wm8994_device_init(wm8994, i2c->irq);
}
-static __devexit int wm8994_i2c_remove(struct i2c_client *i2c)
+static int wm8994_i2c_remove(struct i2c_client *i2c)
{
struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
@@ -744,7 +744,7 @@ static struct i2c_driver wm8994_i2c_driver = {
.of_match_table = wm8994_of_match,
},
.probe = wm8994_i2c_probe,
- .remove = __devexit_p(wm8994_i2c_remove),
+ .remove = wm8994_i2c_remove,
.id_table = wm8994_i2c_id,
};
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 820826270b62..705b881e186d 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -51,7 +51,7 @@ static const struct ad_dpot_bus_ops bops = {
.write_r8d16 = write_r8d16,
};
-static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
+static int ad_dpot_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ad_dpot_bus_data bdata = {
@@ -68,7 +68,7 @@ static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
return ad_dpot_probe(&client->dev, &bdata, id->driver_data, id->name);
}
-static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
+static int ad_dpot_i2c_remove(struct i2c_client *client)
{
return ad_dpot_remove(&client->dev);
}
@@ -109,7 +109,7 @@ static struct i2c_driver ad_dpot_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = ad_dpot_i2c_probe,
- .remove = __devexit_p(ad_dpot_i2c_remove),
+ .remove = ad_dpot_i2c_remove,
.id_table = ad_dpot_id,
};
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
index f62317540d00..9da04ede04f3 100644
--- a/drivers/misc/ad525x_dpot-spi.c
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -75,7 +75,7 @@ static const struct ad_dpot_bus_ops bops = {
.write_r8d8 = write16,
.write_r8d16 = write24,
};
-static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
+static int ad_dpot_spi_probe(struct spi_device *spi)
{
struct ad_dpot_bus_data bdata = {
.client = spi,
@@ -87,7 +87,7 @@ static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
spi_get_device_id(spi)->name);
}
-static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
+static int ad_dpot_spi_remove(struct spi_device *spi)
{
return ad_dpot_remove(&spi->dev);
}
@@ -131,7 +131,7 @@ static struct spi_driver ad_dpot_spi_driver = {
.owner = THIS_MODULE,
},
.probe = ad_dpot_spi_probe,
- .remove = __devexit_p(ad_dpot_spi_remove),
+ .remove = ad_dpot_spi_remove,
.id_table = ad_dpot_spi_id,
};
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 6938f1be664d..8f99e8e3f0ac 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -641,7 +641,7 @@ static const struct attribute_group ad525x_group_commands = {
.attrs = ad525x_attributes_commands,
};
-__devinit int ad_dpot_add_files(struct device *dev,
+int ad_dpot_add_files(struct device *dev,
unsigned features, unsigned rdac)
{
int err = sysfs_create_file(&dev->kobj,
@@ -685,7 +685,7 @@ inline void ad_dpot_remove_files(struct device *dev,
}
}
-int __devinit ad_dpot_probe(struct device *dev,
+int ad_dpot_probe(struct device *dev,
struct ad_dpot_bus_data *bdata, unsigned long devid,
const char *name)
{
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 0314773f6db3..d648b0893027 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -68,7 +68,7 @@ static int als_wait_for_data_ready(struct device *dev)
ret = i2c_smbus_read_byte_data(client, 0x86);
} while (!(ret & 0x80) && retry--);
- if (!retry) {
+ if (retry < 0) {
dev_warn(dev, "timeout waiting for data ready\n");
return -ETIMEDOUT;
}
@@ -254,7 +254,7 @@ als_error1:
return res;
}
-static int __devexit apds9802als_remove(struct i2c_client *client)
+static int apds9802als_remove(struct i2c_client *client)
{
struct als_data *data = i2c_get_clientdata(client);
@@ -326,7 +326,7 @@ static struct i2c_driver apds9802als_driver = {
.pm = APDS9802ALS_PM_OPS,
},
.probe = apds9802als_probe,
- .remove = __devexit_p(apds9802als_remove),
+ .remove = apds9802als_remove,
.suspend = apds9802als_suspend,
.resume = apds9802als_resume,
.id_table = apds9802als_id,
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index ee74244aa03b..0e67f8263cd8 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1047,7 +1047,7 @@ static struct attribute_group apds990x_attribute_group[] = {
{.attrs = sysfs_attrs_ctrl },
};
-static int __devinit apds990x_probe(struct i2c_client *client,
+static int apds990x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct apds990x_chip *chip;
@@ -1181,7 +1181,7 @@ fail1:
return err;
}
-static int __devexit apds990x_remove(struct i2c_client *client)
+static int apds990x_remove(struct i2c_client *client)
{
struct apds990x_chip *chip = i2c_get_clientdata(client);
@@ -1275,7 +1275,7 @@ static struct i2c_driver apds990x_driver = {
.pm = &apds990x_pm_ops,
},
.probe = apds990x_probe,
- .remove = __devexit_p(apds990x_remove),
+ .remove = apds990x_remove,
.id_table = apds990x_id,
};
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 5bb187781074..c58f9abcb356 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -137,7 +137,7 @@ out:
return retval;
}
-static int __devexit ssc_remove(struct platform_device *pdev)
+static int ssc_remove(struct platform_device *pdev)
{
struct ssc_device *ssc = platform_get_drvdata(pdev);
@@ -152,7 +152,7 @@ static int __devexit ssc_remove(struct platform_device *pdev)
}
static struct platform_driver ssc_driver = {
- .remove = __devexit_p(ssc_remove),
+ .remove = ssc_remove,
.driver = {
.name = "ssc",
.owner = THIS_MODULE,
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 3d56ae7ef8de..2ed8fc3be7e6 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1162,7 +1162,7 @@ static struct attribute_group bh1770_attribute_group = {
.attrs = sysfs_attrs
};
-static int __devinit bh1770_probe(struct i2c_client *client,
+static int bh1770_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct bh1770_chip *chip;
@@ -1285,7 +1285,7 @@ fail1:
return err;
}
-static int __devexit bh1770_remove(struct i2c_client *client)
+static int bh1770_remove(struct i2c_client *client)
{
struct bh1770_chip *chip = i2c_get_clientdata(client);
@@ -1395,7 +1395,7 @@ static struct i2c_driver bh1770_driver = {
.pm = &bh1770_pm_ops,
},
.probe = bh1770_probe,
- .remove = __devexit_p(bh1770_remove),
+ .remove = bh1770_remove,
.id_table = bh1770_id,
};
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index f1f9877f3fdf..cf03d0abf33e 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -144,7 +144,7 @@ static const struct attribute_group bh1780_attr_group = {
.attrs = bh1780_attributes,
};
-static int __devinit bh1780_probe(struct i2c_client *client,
+static int bh1780_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
@@ -185,7 +185,7 @@ err_op_failed:
return ret;
}
-static int __devexit bh1780_remove(struct i2c_client *client)
+static int bh1780_remove(struct i2c_client *client)
{
struct bh1780_data *ddata;
@@ -248,7 +248,7 @@ static const struct i2c_device_id bh1780_id[] = {
static struct i2c_driver bh1780_driver = {
.probe = bh1780_probe,
- .remove = __devexit_p(bh1780_remove),
+ .remove = bh1780_remove,
.id_table = bh1780_id,
.driver = {
.name = "bh1780",
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
index a4f33c995ea1..3abfcecf8424 100644
--- a/drivers/misc/bmp085-i2c.c
+++ b/drivers/misc/bmp085-i2c.c
@@ -36,7 +36,7 @@ static int bmp085_i2c_detect(struct i2c_client *client,
return bmp085_detect(&client->dev);
}
-static int __devinit bmp085_i2c_probe(struct i2c_client *client,
+static int bmp085_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
@@ -71,7 +71,7 @@ static struct i2c_driver bmp085_i2c_driver = {
},
.id_table = bmp085_id,
.probe = bmp085_i2c_probe,
- .remove = __devexit_p(bmp085_i2c_remove),
+ .remove = bmp085_i2c_remove,
.detect = bmp085_i2c_detect,
.address_list = normal_i2c
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
index 5e982af99730..d6a52659cf24 100644
--- a/drivers/misc/bmp085-spi.c
+++ b/drivers/misc/bmp085-spi.c
@@ -22,7 +22,7 @@
#include <linux/err.h>
#include "bmp085.h"
-static int __devinit bmp085_spi_probe(struct spi_device *client)
+static int bmp085_spi_probe(struct spi_device *client)
{
int err;
struct regmap *regmap;
@@ -70,7 +70,7 @@ static struct spi_driver bmp085_spi_driver = {
},
.id_table = bmp085_id,
.probe = bmp085_spi_probe,
- .remove = __devexit_p(bmp085_spi_remove)
+ .remove = bmp085_spi_remove
};
module_spi_driver(bmp085_spi_driver);
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 62e418293b7e..849e2fed4da2 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -420,7 +420,7 @@ struct regmap_config bmp085_regmap_config = {
};
EXPORT_SYMBOL_GPL(bmp085_regmap_config);
-__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
+int bmp085_probe(struct device *dev, struct regmap *regmap)
{
struct bmp085_data *data;
int err = 0;
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index 9d5eed754666..2e50f811ff59 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -30,7 +30,7 @@ void cb710_pci_update_config_reg(struct pci_dev *pdev,
EXPORT_SYMBOL_GPL(cb710_pci_update_config_reg);
/* Some magic writes based on Windows driver init code */
-static int __devinit cb710_pci_configure(struct pci_dev *pdev)
+static int cb710_pci_configure(struct pci_dev *pdev)
{
unsigned int devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
struct pci_dev *pdev0;
@@ -96,7 +96,7 @@ static void cb710_release_slot(struct device *dev)
#endif
}
-static int __devinit cb710_register_slot(struct cb710_chip *chip,
+static int cb710_register_slot(struct cb710_chip *chip,
unsigned slot_mask, unsigned io_offset, const char *name)
{
int nr = chip->slots;
@@ -201,7 +201,7 @@ static int cb710_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
-static int __devinit cb710_probe(struct pci_dev *pdev,
+static int cb710_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct cb710_chip *chip;
@@ -305,7 +305,7 @@ unreg_mmc:
return err;
}
-static void __devexit cb710_remove_one(struct pci_dev *pdev)
+static void cb710_remove_one(struct pci_dev *pdev)
{
struct cb710_chip *chip = pci_get_drvdata(pdev);
unsigned long flags;
@@ -332,7 +332,7 @@ static struct pci_driver cb710_driver = {
.name = KBUILD_MODNAME,
.id_table = cb710_pci_tbl,
.probe = cb710_probe,
- .remove = __devexit_p(cb710_remove_one),
+ .remove = cb710_remove_one,
#ifdef CONFIG_PM
.suspend = cb710_suspend,
.resume = cb710_resume,
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index f505a40a8f49..9858f36dad8b 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -246,7 +246,7 @@ EXPORT_SYMBOL_GPL(cs5535_mfgpt_write);
* Jordan tells me that he and Mitch once played w/ it, but it's unclear
* what the results of that were (and they experienced some instability).
*/
-static void __devinit reset_all_timers(void)
+static void reset_all_timers(void)
{
uint32_t val, dummy;
@@ -262,7 +262,7 @@ static void __devinit reset_all_timers(void)
* In other cases (such as with VSAless OpenFirmware), the system firmware
* leaves timers available for us to use.
*/
-static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+static int scan_timers(struct cs5535_mfgpt_chip *mfgpt)
{
struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
unsigned long flags;
@@ -289,7 +289,7 @@ static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
return timers;
}
-static int __devinit cs5535_mfgpt_probe(struct platform_device *pdev)
+static int cs5535_mfgpt_probe(struct platform_device *pdev)
{
struct resource *res;
int err = -EIO, t;
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index ab1ad41786d1..2baeec56edfe 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -656,7 +656,7 @@ err_out:
return err;
}
-static int __devexit at24_remove(struct i2c_client *client)
+static int at24_remove(struct i2c_client *client)
{
struct at24_data *at24;
int i;
@@ -680,7 +680,7 @@ static struct i2c_driver at24_driver = {
.owner = THIS_MODULE,
},
.probe = at24_probe,
- .remove = __devexit_p(at24_remove),
+ .remove = at24_remove,
.id_table = at24_ids,
};
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 4ed93dd54116..b08cf8a08789 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -459,7 +459,7 @@ fail:
return err;
}
-static int __devexit at25_remove(struct spi_device *spi)
+static int at25_remove(struct spi_device *spi)
{
struct at25_data *at25;
@@ -477,7 +477,7 @@ static struct spi_driver at25_driver = {
.owner = THIS_MODULE,
},
.probe = at25_probe,
- .remove = __devexit_p(at25_remove),
+ .remove = at25_remove,
};
module_spi_driver(at25_driver);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index ce3fe3633dd7..a6b5d5e73485 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -309,7 +309,7 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev,
}
static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
-static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
+static int eeprom_93xx46_probe(struct spi_device *spi)
{
struct eeprom_93xx46_platform_data *pd;
struct eeprom_93xx46_dev *edev;
@@ -370,7 +370,7 @@ fail:
return err;
}
-static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
+static int eeprom_93xx46_remove(struct spi_device *spi)
{
struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
@@ -389,7 +389,7 @@ static struct spi_driver eeprom_93xx46_driver = {
.owner = THIS_MODULE,
},
.probe = eeprom_93xx46_probe,
- .remove = __devexit_p(eeprom_93xx46_remove),
+ .remove = eeprom_93xx46_remove,
};
module_spi_driver(eeprom_93xx46_driver);
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
index ac96c3a4034a..e8cbb1c59f4c 100644
--- a/drivers/misc/fsa9480.c
+++ b/drivers/misc/fsa9480.c
@@ -407,7 +407,7 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
return 0;
}
-static int __devinit fsa9480_probe(struct i2c_client *client,
+static int fsa9480_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -462,7 +462,7 @@ fail1:
return ret;
}
-static int __devexit fsa9480_remove(struct i2c_client *client)
+static int fsa9480_remove(struct i2c_client *client)
{
struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
if (client->irq)
@@ -533,7 +533,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
.name = "fsa9480",
},
.probe = fsa9480_probe,
- .remove = __devexit_p(fsa9480_remove),
+ .remove = fsa9480_remove,
.resume = fsa9480_resume,
.suspend = fsa9480_suspend,
.id_table = fsa9480_id,
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 12ccdf94e4fa..621c7a373390 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -30,7 +30,7 @@
static struct class *ilo_class;
static unsigned int ilo_major;
-static unsigned int max_ccb = MIN_CCB;
+static unsigned int max_ccb = 16;
static char ilo_hwdev[MAX_ILO_DEV];
static inline int get_entry_id(int entry)
@@ -686,7 +686,7 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
pci_iounmap(pdev, hw->mmio_vaddr);
}
-static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
{
int error = -ENOMEM;
@@ -725,6 +725,9 @@ static void ilo_remove(struct pci_dev *pdev)
int i, minor;
struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
+ if (!ilo_hw)
+ return;
+
clear_device(ilo_hw);
minor = MINOR(ilo_hw->cdev.dev);
@@ -748,12 +751,16 @@ static void ilo_remove(struct pci_dev *pdev)
ilo_hwdev[(minor / max_ccb)] = 0;
}
-static int __devinit ilo_probe(struct pci_dev *pdev,
+static int ilo_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int devnum, minor, start, error;
+ int devnum, minor, start, error = 0;
struct ilo_hwinfo *ilo_hw;
+ /* Ignore subsystem_device = 0x1979 (set by BIOS) */
+ if (pdev->subsystem_device == 0x1979)
+ goto out;
+
if (max_ccb > MAX_CCB)
max_ccb = MAX_CCB;
else if (max_ccb < MIN_CCB)
@@ -852,7 +859,7 @@ static struct pci_driver ilo_driver = {
.name = ILO_NAME,
.id_table = ilo_devices,
.probe = ilo_probe,
- .remove = __devexit_p(ilo_remove),
+ .remove = ilo_remove,
};
static int __init ilo_init(void)
@@ -892,14 +899,14 @@ static void __exit ilo_exit(void)
class_destroy(ilo_class);
}
-MODULE_VERSION("1.3");
+MODULE_VERSION("1.4");
MODULE_ALIAS(ILO_NAME);
MODULE_DESCRIPTION(ILO_NAME);
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
MODULE_LICENSE("GPL v2");
module_param(max_ccb, uint, 0444);
-MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)");
+MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (16)");
module_init(ilo_init);
module_exit(ilo_exit);
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 168d8008f460..0346d87c5fed 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -62,7 +62,7 @@ module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
-static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
int result;
struct service_processor *sp;
@@ -163,7 +163,7 @@ error_resources:
return result;
}
-static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
+static void ibmasm_remove_one(struct pci_dev *pdev)
{
struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
@@ -198,7 +198,7 @@ static struct pci_driver ibmasm_driver = {
.name = DRIVER_NAME,
.id_table = ibmasm_pci_table,
.probe = ibmasm_init_one,
- .remove = __devexit_p(ibmasm_remove_one),
+ .remove = ibmasm_remove_one,
};
static void __exit ibmasm_exit (void)
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6a7710603a90..06f6ad29ceff 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -139,7 +139,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
* even though the following code utilizes external interrupt registers
* to perform the speed calculation.
*/
-static void __devinit
+static void
ioc4_clock_calibrate(struct ioc4_driver_data *idd)
{
union ioc4_int_out int_out;
@@ -231,7 +231,7 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd)
* on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
* If neither is present, it's a PCI-RT.
*/
-static unsigned int __devinit
+static unsigned int
ioc4_variant(struct ioc4_driver_data *idd)
{
struct pci_dev *pdev = NULL;
@@ -279,7 +279,7 @@ ioc4_load_modules(struct work_struct *work)
static DECLARE_WORK(ioc4_load_modules_work, ioc4_load_modules);
/* Adds a new instance of an IOC4 card */
-static int __devinit
+static int
ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
{
struct ioc4_driver_data *idd;
@@ -415,7 +415,7 @@ out:
}
/* Removes a particular instance of an IOC4 card. */
-static void __devexit
+static void
ioc4_remove(struct pci_dev *pdev)
{
struct ioc4_submodule *is;
@@ -466,7 +466,7 @@ static struct pci_driver ioc4_driver = {
.name = "IOC4",
.id_table = ioc4_id_table,
.probe = ioc4_probe,
- .remove = __devexit_p(ioc4_remove),
+ .remove = ioc4_remove,
};
MODULE_DEVICE_TABLE(pci, ioc4_id_table);
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index eb5de2e210d7..29b306c6bdb3 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -365,7 +365,7 @@ static int isl29003_init_client(struct i2c_client *client)
* I2C layer
*/
-static int __devinit isl29003_probe(struct i2c_client *client,
+static int isl29003_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -401,7 +401,7 @@ exit_kfree:
return err;
}
-static int __devexit isl29003_remove(struct i2c_client *client)
+static int isl29003_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group);
isl29003_set_power_state(client, 0);
@@ -451,7 +451,7 @@ static struct i2c_driver isl29003_driver = {
.suspend = isl29003_suspend,
.resume = isl29003_resume,
.probe = isl29003_probe,
- .remove = __devexit_p(isl29003_remove),
+ .remove = isl29003_remove,
.id_table = isl29003_id,
};
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index 60ec8689d6e3..7c97550240f1 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -114,7 +114,7 @@ static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
#endif
-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+static int lis3lv02d_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
@@ -191,7 +191,7 @@ fail:
return ret;
}
-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+static int lis3lv02d_i2c_remove(struct i2c_client *client)
{
struct lis3lv02d *lis3 = i2c_get_clientdata(client);
struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
@@ -280,7 +280,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
},
.probe = lis3lv02d_i2c_probe,
- .remove = __devexit_p(lis3lv02d_i2c_remove),
+ .remove = lis3lv02d_i2c_remove,
.id_table = lis3lv02d_id,
};
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
index ccb6475fa059..9aa2bd2a71ae 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -69,7 +69,7 @@ static struct of_device_id lis302dl_spi_dt_ids[] = {
MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
#endif
-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
+static int lis302dl_spi_probe(struct spi_device *spi)
{
int ret;
@@ -100,7 +100,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
return lis3lv02d_init_device(&lis3_dev);
}
-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
+static int lis302dl_spi_remove(struct spi_device *spi)
{
struct lis3lv02d *lis3 = spi_get_drvdata(spi);
lis3lv02d_joystick_disable(lis3);
@@ -144,7 +144,7 @@ static struct spi_driver lis302dl_spi_driver = {
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
},
.probe = lis302dl_spi_probe,
- .remove = __devexit_p(lis302dl_spi_remove),
+ .remove = lis302dl_spi_remove,
};
module_spi_driver(lis302dl_spi_driver);
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 57168db6c7e5..0017842e166c 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -8,4 +8,5 @@ mei-objs += interrupt.o
mei-objs += interface.o
mei-objs += iorw.o
mei-objs += main.o
+mei-objs += amthif.o
mei-objs += wd.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
new file mode 100644
index 000000000000..18794aea6062
--- /dev/null
+++ b/drivers/misc/mei/amthif.c
@@ -0,0 +1,722 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2003-2012, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/uuid.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+
+
+#include "mei_dev.h"
+#include "hw.h"
+#include <linux/mei.h>
+#include "interface.h"
+
+const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
+ 0xa8, 0x46, 0xe0, 0xff, 0x65,
+ 0x81, 0x4c);
+
+/**
+ * mei_amthif_reset_params - initializes mei device iamthif
+ *
+ * @dev: the device structure
+ */
+void mei_amthif_reset_params(struct mei_device *dev)
+{
+ /* reset iamthif parameters. */
+ dev->iamthif_current_cb = NULL;
+ dev->iamthif_msg_buf_size = 0;
+ dev->iamthif_msg_buf_index = 0;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = false;
+ dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ dev->iamthif_timer = 0;
+}
+
+/**
+ * mei_amthif_host_init_ - mei initialization amthif client.
+ *
+ * @dev: the device structure
+ *
+ */
+void mei_amthif_host_init(struct mei_device *dev)
+{
+ int i;
+ unsigned char *msg_buf;
+
+ mei_cl_init(&dev->iamthif_cl, dev);
+ dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
+
+ /* find ME amthi client */
+ i = mei_me_cl_link(dev, &dev->iamthif_cl,
+ &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
+ if (i < 0) {
+ dev_info(&dev->pdev->dev, "failed to find iamthif client.\n");
+ return;
+ }
+
+ /* Assign iamthif_mtu to the value received from ME */
+
+ dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
+ dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
+ dev->me_clients[i].props.max_msg_length);
+
+ kfree(dev->iamthif_msg_buf);
+ dev->iamthif_msg_buf = NULL;
+
+ /* allocate storage for ME message buffer */
+ msg_buf = kcalloc(dev->iamthif_mtu,
+ sizeof(unsigned char), GFP_KERNEL);
+ if (!msg_buf) {
+ dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
+ return;
+ }
+
+ dev->iamthif_msg_buf = msg_buf;
+
+ if (mei_connect(dev, &dev->iamthif_cl)) {
+ dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
+ dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
+ dev->iamthif_cl.host_client_id = 0;
+ } else {
+ dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT;
+ }
+}
+
+/**
+ * mei_amthif_find_read_list_entry - finds a amthilist entry for current file
+ *
+ * @dev: the device structure
+ * @file: pointer to file object
+ *
+ * returns returned a list entry on success, NULL on failure.
+ */
+struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
+ struct file *file)
+{
+ struct mei_cl_cb *pos = NULL;
+ struct mei_cl_cb *next = NULL;
+
+ list_for_each_entry_safe(pos, next,
+ &dev->amthif_rd_complete_list.list, list) {
+ if (pos->cl && pos->cl == &dev->iamthif_cl &&
+ pos->file_object == file)
+ return pos;
+ }
+ return NULL;
+}
+
+
+/**
+ * mei_amthif_read - read data from AMTHIF client
+ *
+ * @dev: the device structure
+ * @if_num: minor number
+ * @file: pointer to file object
+ * @*ubuf: pointer to user data in user space
+ * @length: data length to read
+ * @offset: data read offset
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * returns
+ * returned data length on success,
+ * zero if no data to read,
+ * negative on failure.
+ */
+int mei_amthif_read(struct mei_device *dev, struct file *file,
+ char __user *ubuf, size_t length, loff_t *offset)
+{
+ int rets;
+ int wait_ret;
+ struct mei_cl_cb *cb = NULL;
+ struct mei_cl *cl = file->private_data;
+ unsigned long timeout;
+ int i;
+
+ /* Only Posible if we are in timeout */
+ if (!cl || cl != &dev->iamthif_cl) {
+ dev_dbg(&dev->pdev->dev, "bad file ext.\n");
+ return -ETIMEDOUT;
+ }
+
+ i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
+
+ if (i < 0) {
+ dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
+ return -ENODEV;
+ }
+ dev_dbg(&dev->pdev->dev, "checking amthi data\n");
+ cb = mei_amthif_find_read_list_entry(dev, file);
+
+ /* Check for if we can block or not*/
+ if (cb == NULL && file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+
+ dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
+ while (cb == NULL) {
+ /* unlock the Mutex */
+ mutex_unlock(&dev->device_lock);
+
+ wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
+ (cb = mei_amthif_find_read_list_entry(dev, file)));
+
+ if (wait_ret)
+ return -ERESTARTSYS;
+
+ dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
+
+ /* Locking again the Mutex */
+ mutex_lock(&dev->device_lock);
+ }
+
+
+ dev_dbg(&dev->pdev->dev, "Got amthi data\n");
+ dev->iamthif_timer = 0;
+
+ if (cb) {
+ timeout = cb->read_time +
+ mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
+ dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
+ timeout);
+
+ if (time_after(jiffies, timeout)) {
+ dev_dbg(&dev->pdev->dev, "amthi Time out\n");
+ /* 15 sec for the message has expired */
+ list_del(&cb->list);
+ rets = -ETIMEDOUT;
+ goto free;
+ }
+ }
+ /* if the whole message will fit remove it from the list */
+ if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
+ list_del(&cb->list);
+ else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
+ /* end of the message has been reached */
+ list_del(&cb->list);
+ rets = 0;
+ goto free;
+ }
+ /* else means that not full buffer will be read and do not
+ * remove message from deletion list
+ */
+
+ dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
+ cb->response_buffer.size);
+ dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx);
+
+ /* length is being turncated to PAGE_SIZE, however,
+ * the buf_idx may point beyond */
+ length = min_t(size_t, length, (cb->buf_idx - *offset));
+
+ if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
+ rets = -EFAULT;
+ else {
+ rets = length;
+ if ((*offset + length) < cb->buf_idx) {
+ *offset += length;
+ goto out;
+ }
+ }
+free:
+ dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
+ *offset = 0;
+ mei_io_cb_free(cb);
+out:
+ return rets;
+}
+
+/**
+ * mei_amthif_send_cmd - send amthif command to the ME
+ *
+ * @dev: the device structure
+ * @cb: mei call back struct
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+ struct mei_msg_hdr mei_hdr;
+ int ret;
+
+ if (!dev || !cb)
+ return -ENODEV;
+
+ dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
+
+ dev->iamthif_state = MEI_IAMTHIF_WRITING;
+ dev->iamthif_current_cb = cb;
+ dev->iamthif_file_object = cb->file_object;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = true;
+ dev->iamthif_msg_buf_size = cb->request_buffer.size;
+ memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
+ cb->request_buffer.size);
+
+ ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
+ if (ret < 0)
+ return ret;
+
+ if (ret && dev->mei_host_buffer_is_empty) {
+ ret = 0;
+ dev->mei_host_buffer_is_empty = false;
+ if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
+ mei_hdr.length = mei_hbuf_max_data(dev);
+ mei_hdr.msg_complete = 0;
+ } else {
+ mei_hdr.length = cb->request_buffer.size;
+ mei_hdr.msg_complete = 1;
+ }
+
+ mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
+ mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
+ mei_hdr.reserved = 0;
+ dev->iamthif_msg_buf_index += mei_hdr.length;
+ if (mei_write_message(dev, &mei_hdr,
+ (unsigned char *)(dev->iamthif_msg_buf),
+ mei_hdr.length))
+ return -ENODEV;
+
+ if (mei_hdr.msg_complete) {
+ if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
+ return -ENODEV;
+ dev->iamthif_flow_control_pending = true;
+ dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
+ dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
+ dev->iamthif_current_cb = cb;
+ dev->iamthif_file_object = cb->file_object;
+ list_add_tail(&cb->list, &dev->write_waiting_list.list);
+ } else {
+ dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n");
+ list_add_tail(&cb->list, &dev->write_list.list);
+ }
+ } else {
+ if (!(dev->mei_host_buffer_is_empty))
+ dev_dbg(&dev->pdev->dev, "host buffer is not empty");
+
+ dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
+ list_add_tail(&cb->list, &dev->write_list.list);
+ }
+ return 0;
+}
+
+/**
+ * mei_amthif_write - write amthif data to amthif client
+ *
+ * @dev: the device structure
+ * @cb: mei call back struct
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+ int ret;
+
+ if (!dev || !cb)
+ return -ENODEV;
+
+ ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
+ if (ret)
+ return ret;
+
+ cb->fop_type = MEI_FOP_IOCTL;
+
+ if (!list_empty(&dev->amthif_cmd_list.list) ||
+ dev->iamthif_state != MEI_IAMTHIF_IDLE) {
+ dev_dbg(&dev->pdev->dev,
+ "amthif state = %d\n", dev->iamthif_state);
+ dev_dbg(&dev->pdev->dev, "AMTHIF: add cb to the wait list\n");
+ list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
+ return 0;
+ }
+ return mei_amthif_send_cmd(dev, cb);
+}
+/**
+ * mei_amthif_run_next_cmd
+ *
+ * @dev: the device structure
+ *
+ * returns 0 on success, <0 on failure.
+ */
+void mei_amthif_run_next_cmd(struct mei_device *dev)
+{
+ struct mei_cl_cb *pos = NULL;
+ struct mei_cl_cb *next = NULL;
+ int status;
+
+ if (!dev)
+ return;
+
+ dev->iamthif_msg_buf_size = 0;
+ dev->iamthif_msg_buf_index = 0;
+ dev->iamthif_canceled = false;
+ dev->iamthif_ioctl = true;
+ dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ dev->iamthif_timer = 0;
+ dev->iamthif_file_object = NULL;
+
+ dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
+
+ list_for_each_entry_safe(pos, next, &dev->amthif_cmd_list.list, list) {
+ list_del(&pos->list);
+
+ if (pos->cl && pos->cl == &dev->iamthif_cl) {
+ status = mei_amthif_send_cmd(dev, pos);
+ if (status) {
+ dev_dbg(&dev->pdev->dev,
+ "amthi write failed status = %d\n",
+ status);
+ return;
+ }
+ break;
+ }
+ }
+}
+
+
+unsigned int mei_amthif_poll(struct mei_device *dev,
+ struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+ mutex_unlock(&dev->device_lock);
+ poll_wait(file, &dev->iamthif_cl.wait, wait);
+ mutex_lock(&dev->device_lock);
+ if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
+ dev->iamthif_file_object == file) {
+ mask |= (POLLIN | POLLRDNORM);
+ dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
+ mei_amthif_run_next_cmd(dev);
+ }
+ return mask;
+}
+
+
+
+/**
+ * mei_amthif_irq_process_completed - processes completed iamthif operation.
+ *
+ * @dev: the device structure.
+ * @slots: free slots.
+ * @cb_pos: callback block.
+ * @cl: private data of the file object.
+ * @cmpl_list: complete list.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
+ struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
+{
+ struct mei_msg_hdr *mei_hdr;
+ struct mei_cl *cl = cb->cl;
+ size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
+ size_t msg_slots = mei_data2slots(len);
+
+ mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
+ mei_hdr->host_addr = cl->host_client_id;
+ mei_hdr->me_addr = cl->me_client_id;
+ mei_hdr->reserved = 0;
+
+ if (*slots >= msg_slots) {
+ mei_hdr->length = len;
+ mei_hdr->msg_complete = 1;
+ /* Split the message only if we can write the whole host buffer */
+ } else if (*slots == dev->hbuf_depth) {
+ msg_slots = *slots;
+ len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+ mei_hdr->length = len;
+ mei_hdr->msg_complete = 0;
+ } else {
+ /* wait for next time the host buffer is empty */
+ return 0;
+ }
+
+ dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
+ mei_hdr->length, mei_hdr->msg_complete);
+
+ *slots -= msg_slots;
+ if (mei_write_message(dev, mei_hdr,
+ dev->iamthif_msg_buf + dev->iamthif_msg_buf_index,
+ mei_hdr->length)) {
+ dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ cl->status = -ENODEV;
+ list_del(&cb->list);
+ return -ENODEV;
+ }
+
+ if (mei_flow_ctrl_reduce(dev, cl))
+ return -ENODEV;
+
+ dev->iamthif_msg_buf_index += mei_hdr->length;
+ cl->status = 0;
+
+ if (mei_hdr->msg_complete) {
+ dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
+ dev->iamthif_flow_control_pending = true;
+
+ /* save iamthif cb sent to amthi client */
+ cb->buf_idx = dev->iamthif_msg_buf_index;
+ dev->iamthif_current_cb = cb;
+
+ list_move_tail(&cb->list, &dev->write_waiting_list.list);
+ }
+
+
+ return 0;
+}
+
+/**
+ * mei_amthif_irq_read_message - read routine after ISR to
+ * handle the read amthi message
+ *
+ * @complete_list: An instance of our list structure
+ * @dev: the device structure
+ * @mei_hdr: header of amthi message
+ *
+ * returns 0 on success, <0 on failure.
+ */
+int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
+ struct mei_device *dev, struct mei_msg_hdr *mei_hdr)
+{
+ struct mei_cl_cb *cb;
+ unsigned char *buffer;
+
+ BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
+ BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
+
+ buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
+ BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
+
+ mei_read_slots(dev, buffer, mei_hdr->length);
+
+ dev->iamthif_msg_buf_index += mei_hdr->length;
+
+ if (!mei_hdr->msg_complete)
+ return 0;
+
+ dev_dbg(&dev->pdev->dev,
+ "amthi_message_buffer_index =%d\n",
+ mei_hdr->length);
+
+ dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
+ if (!dev->iamthif_current_cb)
+ return -ENODEV;
+
+ cb = dev->iamthif_current_cb;
+ dev->iamthif_current_cb = NULL;
+
+ if (!cb->cl)
+ return -ENODEV;
+
+ dev->iamthif_stall_timer = 0;
+ cb->buf_idx = dev->iamthif_msg_buf_index;
+ cb->read_time = jiffies;
+ if (dev->iamthif_ioctl && cb->cl == &dev->iamthif_cl) {
+ /* found the iamthif cb */
+ dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
+ dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
+ list_add_tail(&cb->list, &complete_list->list);
+ }
+ return 0;
+}
+
+/**
+ * mei_amthif_irq_read - prepares to read amthif data.
+ *
+ * @dev: the device structure.
+ * @slots: free slots.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
+{
+
+ if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
+ + sizeof(struct hbm_flow_control))) {
+ return -EMSGSIZE;
+ }
+ *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
+ if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
+ dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
+ return -EIO;
+ }
+
+ dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
+ dev->iamthif_state = MEI_IAMTHIF_READING;
+ dev->iamthif_flow_control_pending = false;
+ dev->iamthif_msg_buf_index = 0;
+ dev->iamthif_msg_buf_size = 0;
+ dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
+ dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
+ return 0;
+}
+
+/**
+ * mei_amthif_complete - complete amthif callback.
+ *
+ * @dev: the device structure.
+ * @cb_pos: callback block.
+ */
+void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
+{
+ if (dev->iamthif_canceled != 1) {
+ dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
+ dev->iamthif_stall_timer = 0;
+ memcpy(cb->response_buffer.data,
+ dev->iamthif_msg_buf,
+ dev->iamthif_msg_buf_index);
+ list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
+ dev_dbg(&dev->pdev->dev, "amthi read completed\n");
+ dev->iamthif_timer = jiffies;
+ dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
+ dev->iamthif_timer);
+ } else {
+ mei_amthif_run_next_cmd(dev);
+ }
+
+ dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
+ wake_up_interruptible(&dev->iamthif_cl.wait);
+}
+
+/**
+ * mei_clear_list - removes all callbacks associated with file
+ * from mei_cb_list
+ *
+ * @dev: device structure.
+ * @file: file structure
+ * @mei_cb_list: callbacks list
+ *
+ * mei_clear_list is called to clear resources associated with file
+ * when application calls close function or Ctrl-C was pressed
+ *
+ * returns true if callback removed from the list, false otherwise
+ */
+static bool mei_clear_list(struct mei_device *dev,
+ const struct file *file, struct list_head *mei_cb_list)
+{
+ struct mei_cl_cb *cb_pos = NULL;
+ struct mei_cl_cb *cb_next = NULL;
+ bool removed = false;
+
+ /* list all list member */
+ list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
+ /* check if list member associated with a file */
+ if (file == cb_pos->file_object) {
+ /* remove member from the list */
+ list_del(&cb_pos->list);
+ /* check if cb equal to current iamthif cb */
+ if (dev->iamthif_current_cb == cb_pos) {
+ dev->iamthif_current_cb = NULL;
+ /* send flow control to iamthif client */
+ mei_send_flow_control(dev, &dev->iamthif_cl);
+ }
+ /* free all allocated buffers */
+ mei_io_cb_free(cb_pos);
+ cb_pos = NULL;
+ removed = true;
+ }
+ }
+ return removed;
+}
+
+/**
+ * mei_clear_lists - removes all callbacks associated with file
+ *
+ * @dev: device structure
+ * @file: file structure
+ *
+ * mei_clear_lists is called to clear resources associated with file
+ * when application calls close function or Ctrl-C was pressed
+ *
+ * returns true if callback removed from the list, false otherwise
+ */
+static bool mei_clear_lists(struct mei_device *dev, struct file *file)
+{
+ bool removed = false;
+
+ /* remove callbacks associated with a file */
+ mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
+ if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list))
+ removed = true;
+
+ mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
+
+ if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
+ removed = true;
+
+ if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
+ removed = true;
+
+ if (mei_clear_list(dev, file, &dev->write_list.list))
+ removed = true;
+
+ /* check if iamthif_current_cb not NULL */
+ if (dev->iamthif_current_cb && !removed) {
+ /* check file and iamthif current cb association */
+ if (dev->iamthif_current_cb->file_object == file) {
+ /* remove cb */
+ mei_io_cb_free(dev->iamthif_current_cb);
+ dev->iamthif_current_cb = NULL;
+ removed = true;
+ }
+ }
+ return removed;
+}
+
+/**
+* mei_amthif_release - the release function
+*
+* @inode: pointer to inode structure
+* @file: pointer to file structure
+*
+* returns 0 on success, <0 on error
+*/
+int mei_amthif_release(struct mei_device *dev, struct file *file)
+{
+ if (dev->open_handle_count > 0)
+ dev->open_handle_count--;
+
+ if (dev->iamthif_file_object == file &&
+ dev->iamthif_state != MEI_IAMTHIF_IDLE) {
+
+ dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
+ dev->iamthif_state);
+ dev->iamthif_canceled = true;
+ if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
+ dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
+ mei_amthif_run_next_cmd(dev);
+ }
+ }
+
+ if (mei_clear_lists(dev, file))
+ dev->iamthif_state = MEI_IAMTHIF_IDLE;
+
+ return 0;
+}
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 9700532f02f6..be8ca6b333ca 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -20,16 +20,16 @@
#include <linux/uuid.h>
/*
- * Timeouts
+ * Timeouts in Seconds
*/
-#define MEI_INTEROP_TIMEOUT (HZ * 7)
-#define MEI_CONNECT_TIMEOUT 3 /* at least 2 seconds */
+#define MEI_INTEROP_TIMEOUT 7 /* Timeout on ready message */
+#define MEI_CONNECT_TIMEOUT 3 /* HPS: at least 2 seconds */
-#define CONNECT_TIMEOUT 15 /* HPS definition */
-#define INIT_CLIENTS_TIMEOUT 15 /* HPS definition */
+#define MEI_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */
+#define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */
-#define IAMTHIF_STALL_TIMER 12 /* seconds */
-#define IAMTHIF_READ_TIMER 10000 /* ms */
+#define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */
+#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */
/*
* Internal Clients Number
@@ -293,6 +293,14 @@ struct hbm_props_response {
struct mei_client_properties client_properties;
} __packed;
+/**
+ * struct hbm_client_connect_request - connect/disconnect request
+ *
+ * @hbm_cmd - bus message command header
+ * @me_addr - address of the client in ME
+ * @host_addr - address of the client in the driver
+ * @reserved
+ */
struct hbm_client_connect_request {
u8 hbm_cmd;
u8 me_addr;
@@ -300,6 +308,14 @@ struct hbm_client_connect_request {
u8 reserved;
} __packed;
+/**
+ * struct hbm_client_connect_response - connect/disconnect response
+ *
+ * @hbm_cmd - bus message command header
+ * @me_addr - address of the client in ME
+ * @host_addr - address of the client in the driver
+ * @status - status of the request
+ */
struct hbm_client_connect_response {
u8 hbm_cmd;
u8 me_addr;
@@ -307,12 +323,6 @@ struct hbm_client_connect_response {
u8 status;
} __packed;
-struct hbm_client_disconnect_request {
- u8 hbm_cmd;
- u8 me_addr;
- u8 host_addr;
- u8 reserved[1];
-} __packed;
#define MEI_FC_MESSAGE_RESERVED_LENGTH 5
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 98f1430e3e14..a54cd5567ca2 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -43,21 +43,6 @@ const char *mei_dev_state_str(int state)
}
-const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
- 0xa8, 0x46, 0xe0, 0xff, 0x65,
- 0x81, 0x4c);
-
-/**
- * mei_io_list_init - Sets up a queue list.
- *
- * @list: An instance io list structure
- * @dev: the device structure
- */
-void mei_io_list_init(struct mei_io_list *list)
-{
- /* initialize our queue list */
- INIT_LIST_HEAD(&list->mei_cb.cb_list);
-}
/**
* mei_io_list_flush - removes list entry belonging to cl.
@@ -65,17 +50,15 @@ void mei_io_list_init(struct mei_io_list *list)
* @list: An instance of our list structure
* @cl: private data of the file object
*/
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
{
struct mei_cl_cb *pos;
struct mei_cl_cb *next;
- list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
- if (pos->file_private) {
- struct mei_cl *cl_tmp;
- cl_tmp = (struct mei_cl *)pos->file_private;
- if (mei_cl_cmp_id(cl, cl_tmp))
- list_del(&pos->cb_list);
+ list_for_each_entry_safe(pos, next, &list->list, list) {
+ if (pos->cl) {
+ if (mei_cl_cmp_id(cl, pos->cl))
+ list_del(&pos->list);
}
}
}
@@ -96,31 +79,14 @@ int mei_cl_flush_queues(struct mei_cl *cl)
mei_io_list_flush(&cl->dev->write_waiting_list, cl);
mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
- mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
- mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
+ mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
+ mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
return 0;
}
/**
- * mei_reset_iamthif_params - initializes mei device iamthif
- *
- * @dev: the device structure
- */
-static void mei_reset_iamthif_params(struct mei_device *dev)
-{
- /* reset iamthif parameters. */
- dev->iamthif_current_cb = NULL;
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = false;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->iamthif_timer = 0;
-}
-
-/**
* init_mei_device - allocates and initializes the mei device structure
*
* @pdev: The pci device structure
@@ -144,16 +110,14 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
init_waitqueue_head(&dev->wait_stop_wd);
dev->dev_state = MEI_DEV_INITIALIZING;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->wd_interface_reg = false;
-
mei_io_list_init(&dev->read_list);
mei_io_list_init(&dev->write_list);
mei_io_list_init(&dev->write_waiting_list);
mei_io_list_init(&dev->ctrl_wr_list);
mei_io_list_init(&dev->ctrl_rd_list);
- mei_io_list_init(&dev->amthi_cmd_list);
- mei_io_list_init(&dev->amthi_read_complete_list);
+ mei_io_list_init(&dev->amthif_cmd_list);
+ mei_io_list_init(&dev->amthif_rd_complete_list);
dev->pdev = pdev;
return dev;
}
@@ -196,7 +160,8 @@ int mei_hw_init(struct mei_device *dev)
if (!dev->recvd_msg) {
mutex_unlock(&dev->device_lock);
err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
- dev->recvd_msg, MEI_INTEROP_TIMEOUT);
+ dev->recvd_msg,
+ mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
mutex_lock(&dev->device_lock);
}
@@ -317,15 +282,13 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
cl_pos->timer_count = 0;
}
/* remove entry if already in list */
- dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
- mei_remove_client_from_file_list(dev,
- dev->wd_cl.host_client_id);
+ dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
+ mei_me_cl_unlink(dev, &dev->wd_cl);
- mei_remove_client_from_file_list(dev,
- dev->iamthif_cl.host_client_id);
+ mei_me_cl_unlink(dev, &dev->iamthif_cl);
- mei_reset_iamthif_params(dev);
- dev->extra_write_index = 0;
+ mei_amthif_reset_params(dev);
+ memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
}
dev->me_clients_num = 0;
@@ -351,10 +314,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
}
}
/* remove all waiting requests */
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- list_del(&cb_pos->cb_list);
- mei_free_cb_private(cb_pos);
+ list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) {
+ list_del(&cb_pos->list);
+ mei_io_cb_free(cb_pos);
}
}
@@ -370,31 +332,26 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
void mei_host_start_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
- struct hbm_host_version_request *host_start_req;
+ struct hbm_host_version_request *start_req;
+ const size_t len = sizeof(struct hbm_host_version_request);
+
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
/* host start message */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_version_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_start_req =
- (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
- memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
- host_start_req->hbm_cmd = HOST_START_REQ_CMD;
- host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
- host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
+ start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
+ memset(start_req, 0, len);
+ start_req->hbm_cmd = HOST_START_REQ_CMD;
+ start_req->host_version.major_version = HBM_MAJOR_VERSION;
+ start_req->host_version.minor_version = HBM_MINOR_VERSION;
+
dev->recvd_msg = false;
- if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
- mei_hdr->length)) {
+ if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) {
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
dev->dev_state = MEI_DEV_RESETING;
mei_reset(dev, 1);
}
dev->init_clients_state = MEI_START_MESSAGE;
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
+ dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return ;
}
@@ -408,26 +365,22 @@ void mei_host_start_message(struct mei_device *dev)
void mei_host_enum_clients_message(struct mei_device *dev)
{
struct mei_msg_hdr *mei_hdr;
- struct hbm_host_enum_request *host_enum_req;
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
+ struct hbm_host_enum_request *enum_req;
+ const size_t len = sizeof(struct hbm_host_enum_request);
/* enumerate clients */
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_enum_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
- memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
- host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
- if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
- mei_hdr->length)) {
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+ enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
+ memset(enum_req, 0, sizeof(struct hbm_host_enum_request));
+ enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
+
+ if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) {
dev->dev_state = MEI_DEV_RESETING;
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1);
}
dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
+ dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
return;
}
@@ -470,56 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
dev->me_clients = clients;
return ;
}
-/**
- * host_client_properties - reads properties for client
- *
- * @dev: the device structure
- *
- * returns:
- * < 0 - Error.
- * = 0 - no more clients.
- * = 1 - still have clients to send properties request.
- */
-int mei_host_client_properties(struct mei_device *dev)
+
+void mei_host_client_init(struct work_struct *work)
{
- struct mei_msg_hdr *mei_header;
- struct hbm_props_request *host_cli_req;
- int b;
- u8 client_num = dev->me_client_presentation_num;
-
- b = dev->me_client_index;
- b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
- if (b < MEI_CLIENTS_MAX) {
- dev->me_clients[client_num].client_id = b;
- dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
- mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
- mei_header->host_addr = 0;
- mei_header->me_addr = 0;
- mei_header->length = sizeof(struct hbm_props_request);
- mei_header->msg_complete = 1;
- mei_header->reserved = 0;
-
- host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
-
- memset(host_cli_req, 0, sizeof(struct hbm_props_request));
-
- host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
- host_cli_req->address = b;
-
- if (mei_write_message(dev, mei_header,
- (unsigned char *)host_cli_req,
- mei_header->length)) {
- dev->dev_state = MEI_DEV_RESETING;
- dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
- mei_reset(dev, 1);
- return -EIO;
- }
+ struct mei_device *dev = container_of(work,
+ struct mei_device, init_work);
+ struct mei_client_properties *client_props;
+ int i;
+
+ mutex_lock(&dev->device_lock);
+
+ bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
+ dev->open_handle_count = 0;
+
+ /*
+ * Reserving the first three client IDs
+ * 0: Reserved for MEI Bus Message communications
+ * 1: Reserved for Watchdog
+ * 2: Reserved for AMTHI
+ */
+ bitmap_set(dev->host_clients_map, 0, 3);
+
+ for (i = 0; i < dev->me_clients_num; i++) {
+ client_props = &dev->me_clients[i].props;
+
+ if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
+ mei_amthif_host_init(dev);
+ else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
+ mei_wd_host_init(dev);
+ }
+
+ dev->dev_state = MEI_DEV_ENABLED;
- dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
- dev->me_client_index = b;
- return 1;
+ mutex_unlock(&dev->device_lock);
+}
+
+int mei_host_client_enumerate(struct mei_device *dev)
+{
+
+ struct mei_msg_hdr *mei_hdr;
+ struct hbm_props_request *prop_req;
+ const size_t len = sizeof(struct hbm_props_request);
+ unsigned long next_client_index;
+ u8 client_num;
+
+
+ client_num = dev->me_client_presentation_num;
+
+ next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
+ dev->me_client_index);
+
+ /* We got all client properties */
+ if (next_client_index == MEI_CLIENTS_MAX) {
+ schedule_work(&dev->init_work);
+
+ return 0;
}
+ dev->me_clients[client_num].client_id = next_client_index;
+ dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
+
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+ prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
+
+ memset(prop_req, 0, sizeof(struct hbm_props_request));
+
+
+ prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
+ prop_req->address = next_client_index;
+
+ if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
+ mei_hdr->length)) {
+ dev->dev_state = MEI_DEV_RESETING;
+ dev_err(&dev->pdev->dev, "Properties request command failed\n");
+ mei_reset(dev, 1);
+
+ return -EIO;
+ }
+
+ dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
+ dev->me_client_index = next_client_index;
+
return 0;
}
@@ -557,17 +541,20 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid)
/**
- * mei_me_cl_update_filext - searches for ME client guid
- * sets client_id in mei_file_private if found
+ * mei_me_cl_link - create link between host and me clinet and add
+ * me_cl to the list
+ *
* @dev: the device structure
- * @cl: private file structure to set client_id in
- * @cuuid: searched uuid of ME client
- * @client_id: id of host client to be set in file private structure
+ * @cl: link between me and host client assocated with opened file descriptor
+ * @cuuid: uuid of ME client
+ * @client_id: id of the host client
*
- * returns ME client index
+ * returns ME client index if ME client
+ * -EINVAL on incorrect values
+ * -ENONET if client not found
*/
-int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
- const uuid_le *cuuid, u8 host_cl_id)
+int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
+ const uuid_le *cuuid, u8 host_cl_id)
{
int i;
@@ -587,54 +574,22 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
return -ENOENT;
}
-
/**
- * host_init_iamthif - mei initialization iamthif client.
+ * mei_me_cl_unlink - remove me_cl from the list
*
* @dev: the device structure
- *
+ * @host_client_id: host client id to be removed
*/
-void mei_host_init_iamthif(struct mei_device *dev)
+void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl)
{
- int i;
- unsigned char *msg_buf;
-
- mei_cl_init(&dev->iamthif_cl, dev);
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
-
- /* find ME amthi client */
- i = mei_me_cl_update_filext(dev, &dev->iamthif_cl,
- &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
- if (i < 0) {
- dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
- return;
- }
-
- /* Assign iamthif_mtu to the value received from ME */
-
- dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
- dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
- dev->me_clients[i].props.max_msg_length);
-
- kfree(dev->iamthif_msg_buf);
- dev->iamthif_msg_buf = NULL;
-
- /* allocate storage for ME message buffer */
- msg_buf = kcalloc(dev->iamthif_mtu,
- sizeof(unsigned char), GFP_KERNEL);
- if (!msg_buf) {
- dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
- return;
- }
-
- dev->iamthif_msg_buf = msg_buf;
-
- if (mei_connect(dev, &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
- dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
- dev->iamthif_cl.host_client_id = 0;
- } else {
- dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
+ struct mei_cl *pos, *next;
+ list_for_each_entry_safe(pos, next, &dev->file_list, link) {
+ if (cl->host_client_id == pos->host_client_id) {
+ dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
+ pos->host_client_id, pos->me_client_id);
+ list_del_init(&pos->link);
+ break;
+ }
}
}
@@ -671,9 +626,8 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
*/
int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
{
- int rets, err;
- long timeout = 15; /* 15 seconds */
struct mei_cl_cb *cb;
+ int rets, err;
if (!dev || !cl)
return -ENODEV;
@@ -681,13 +635,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
if (cl->state != MEI_FILE_DISCONNECTING)
return 0;
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
- INIT_LIST_HEAD(&cb->cb_list);
- cb->file_private = cl;
- cb->major_file_operations = MEI_CLOSE;
+ cb->fop_type = MEI_FOP_CLOSE;
if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false;
if (mei_disconnect(dev, cl)) {
@@ -696,17 +648,17 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
goto free;
}
mdelay(10); /* Wait for hardware disconnection ready */
- list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
+ list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
- list_add_tail(&cb->cb_list,
- &dev->ctrl_wr_list.mei_cb.cb_list);
+ list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+
}
mutex_unlock(&dev->device_lock);
err = wait_event_timeout(dev->wait_recvd_msg,
- (MEI_FILE_DISCONNECTED == cl->state),
- timeout * HZ);
+ MEI_FILE_DISCONNECTED == cl->state,
+ mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(&dev->device_lock);
if (MEI_FILE_DISCONNECTED == cl->state) {
@@ -728,29 +680,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
mei_io_list_flush(&dev->ctrl_rd_list, cl);
mei_io_list_flush(&dev->ctrl_wr_list, cl);
free:
- mei_free_cb_private(cb);
+ mei_io_cb_free(cb);
return rets;
}
-/**
- * mei_remove_client_from_file_list -
- * removes file private data from device file list
- *
- * @dev: the device structure
- * @host_client_id: host client id to be removed
- */
-void mei_remove_client_from_file_list(struct mei_device *dev,
- u8 host_client_id)
-{
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (host_client_id == cl_pos->host_client_id) {
- dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- list_del_init(&cl_pos->link);
- break;
- }
- }
-}
diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c
index 509c3957ff45..8de854785960 100644
--- a/drivers/misc/mei/interface.c
+++ b/drivers/misc/mei/interface.c
@@ -292,28 +292,23 @@ int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
- struct hbm_flow_control *mei_flow_control;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_flow_control);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
- memset(mei_flow_control, 0, sizeof(*mei_flow_control));
- mei_flow_control->host_addr = cl->host_client_id;
- mei_flow_control->me_addr = cl->me_client_id;
- mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
- memset(mei_flow_control->reserved, 0,
- sizeof(mei_flow_control->reserved));
+ struct hbm_flow_control *flow_ctrl;
+ const size_t len = sizeof(struct hbm_flow_control);
+
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+ flow_ctrl = (struct hbm_flow_control *)&dev->wr_msg_buf[1];
+ memset(flow_ctrl, 0, len);
+ flow_ctrl->hbm_cmd = MEI_FLOW_CONTROL_CMD;
+ flow_ctrl->host_addr = cl->host_client_id;
+ flow_ctrl->me_addr = cl->me_client_id;
+ /* FIXME: reserved !? */
+ memset(flow_ctrl->reserved, 0, sizeof(flow_ctrl->reserved));
dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_flow_control,
- sizeof(struct hbm_flow_control));
+ (unsigned char *) flow_ctrl, len);
}
/**
@@ -352,26 +347,19 @@ int mei_other_client_is_connecting(struct mei_device *dev,
int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
- struct hbm_client_disconnect_request *mei_cli_disconnect;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_cli_disconnect =
- (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
- memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
- mei_cli_disconnect->host_addr = cl->host_client_id;
- mei_cli_disconnect->me_addr = cl->me_client_id;
- mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
- mei_cli_disconnect->reserved[0] = 0;
+ struct hbm_client_connect_request *req;
+ const size_t len = sizeof(struct hbm_client_connect_request);
- return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_cli_disconnect,
- sizeof(struct hbm_client_disconnect_request));
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+ req = (struct hbm_client_connect_request *)&dev->wr_msg_buf[1];
+ memset(req, 0, len);
+ req->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
+ req->host_addr = cl->host_client_id;
+ req->me_addr = cl->me_client_id;
+ req->reserved = 0;
+
+ return mei_write_message(dev, mei_hdr, (unsigned char *)req, len);
}
/**
@@ -385,23 +373,16 @@ int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
int mei_connect(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_msg_hdr *mei_hdr;
- struct hbm_client_connect_request *mei_cli_connect;
-
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_client_connect_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- mei_cli_connect =
- (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
- mei_cli_connect->host_addr = cl->host_client_id;
- mei_cli_connect->me_addr = cl->me_client_id;
- mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
- mei_cli_connect->reserved = 0;
+ struct hbm_client_connect_request *req;
+ const size_t len = sizeof(struct hbm_client_connect_request);
- return mei_write_message(dev, mei_hdr,
- (unsigned char *) mei_cli_connect,
- sizeof(struct hbm_client_connect_request));
+ mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+
+ req = (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
+ req->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
+ req->host_addr = cl->host_client_id;
+ req->me_addr = cl->me_client_id;
+ req->reserved = 0;
+
+ return mei_write_message(dev, mei_hdr, (unsigned char *) req, len);
}
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 3533edde04a5..04fa2134615e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -57,14 +57,14 @@ irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
*/
static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
{
- if (cb_pos->major_file_operations == MEI_WRITE) {
- mei_free_cb_private(cb_pos);
+ if (cb_pos->fop_type == MEI_FOP_WRITE) {
+ mei_io_cb_free(cb_pos);
cb_pos = NULL;
cl->writing_state = MEI_WRITE_COMPLETE;
if (waitqueue_active(&cl->tx_wait))
wake_up_interruptible(&cl->tx_wait);
- } else if (cb_pos->major_file_operations == MEI_READ &&
+ } else if (cb_pos->fop_type == MEI_FOP_READ &&
MEI_READING == cl->reading_state) {
cl->reading_state = MEI_READ_COMPLETE;
if (waitqueue_active(&cl->rx_wait))
@@ -74,94 +74,6 @@ static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
}
/**
- * _mei_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @cb_pos: callback block.
- */
-static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
-{
- if (dev->iamthif_canceled != 1) {
- dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
- dev->iamthif_stall_timer = 0;
- memcpy(cb_pos->response_buffer.data,
- dev->iamthif_msg_buf,
- dev->iamthif_msg_buf_index);
- list_add_tail(&cb_pos->cb_list,
- &dev->amthi_read_complete_list.mei_cb.cb_list);
- dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
- dev->iamthif_timer = jiffies;
- dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
- dev->iamthif_timer);
- } else {
- mei_run_next_iamthif_cmd(dev);
- }
-
- dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
- wake_up_interruptible(&dev->iamthif_cl.wait);
-}
-
-
-/**
- * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to
- * handle the read amthi message data processing.
- *
- * @complete_list: An instance of our list structure
- * @dev: the device structure
- * @mei_hdr: header of amthi message
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
- struct mei_device *dev,
- struct mei_msg_hdr *mei_hdr)
-{
- struct mei_cl *cl;
- struct mei_cl_cb *cb;
- unsigned char *buffer;
-
- BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
- BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
-
- buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
- BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
-
- mei_read_slots(dev, buffer, mei_hdr->length);
-
- dev->iamthif_msg_buf_index += mei_hdr->length;
-
- if (!mei_hdr->msg_complete)
- return 0;
-
- dev_dbg(&dev->pdev->dev,
- "amthi_message_buffer_index =%d\n",
- mei_hdr->length);
-
- dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
- if (!dev->iamthif_current_cb)
- return -ENODEV;
-
- cb = dev->iamthif_current_cb;
- dev->iamthif_current_cb = NULL;
-
- cl = (struct mei_cl *)cb->file_private;
- if (!cl)
- return -ENODEV;
-
- dev->iamthif_stall_timer = 0;
- cb->information = dev->iamthif_msg_buf_index;
- cb->read_time = jiffies;
- if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
- /* found the iamthif cb */
- dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
- dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
- list_add_tail(&cb->cb_list,
- &complete_list->mei_cb.cb_list);
- }
- return 0;
-}
-
-/**
* _mei_irq_thread_state_ok - checks if mei header matches file private data
*
* @cl: private data of the file object
@@ -188,7 +100,7 @@ static int _mei_irq_thread_state_ok(struct mei_cl *cl,
*
* returns 0 on success, <0 on failure.
*/
-static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
+static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list,
struct mei_device *dev,
struct mei_msg_hdr *mei_hdr)
{
@@ -197,36 +109,36 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
unsigned char *buffer = NULL;
dev_dbg(&dev->pdev->dev, "start client msg\n");
- if (list_empty(&dev->read_list.mei_cb.cb_list))
+ if (list_empty(&dev->read_list.list))
goto quit;
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->read_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
+ list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) {
+ cl = cb_pos->cl;
if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
cl->reading_state = MEI_READING;
- buffer = cb_pos->response_buffer.data + cb_pos->information;
+ buffer = cb_pos->response_buffer.data + cb_pos->buf_idx;
if (cb_pos->response_buffer.size <
- mei_hdr->length + cb_pos->information) {
+ mei_hdr->length + cb_pos->buf_idx) {
dev_dbg(&dev->pdev->dev, "message overflow.\n");
- list_del(&cb_pos->cb_list);
+ list_del(&cb_pos->list);
return -ENOMEM;
}
if (buffer)
mei_read_slots(dev, buffer, mei_hdr->length);
- cb_pos->information += mei_hdr->length;
+ cb_pos->buf_idx += mei_hdr->length;
if (mei_hdr->msg_complete) {
cl->status = 0;
- list_del(&cb_pos->cb_list);
+ list_del(&cb_pos->list);
dev_dbg(&dev->pdev->dev,
"completed read H cl = %d, ME cl = %d, length = %lu\n",
cl->host_client_id,
cl->me_client_id,
- cb_pos->information);
- list_add_tail(&cb_pos->cb_list,
- &complete_list->mei_cb.cb_list);
+ cb_pos->buf_idx);
+
+ list_add_tail(&cb_pos->list,
+ &complete_list->list);
}
break;
@@ -246,37 +158,6 @@ quit:
}
/**
- * _mei_irq_thread_iamthif_read - prepares to read iamthif data.
- *
- * @dev: the device structure.
- * @slots: free slots.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
-{
-
- if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
- + sizeof(struct hbm_flow_control))) {
- return -EMSGSIZE;
- }
- *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
- if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
- dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
- return -EIO;
- }
-
- dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
- dev->iamthif_state = MEI_IAMTHIF_READING;
- dev->iamthif_flow_control_pending = false;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
- dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
- return 0;
-}
-
-/**
* _mei_irq_thread_close - processes close related operation.
*
* @dev: the device structure.
@@ -290,26 +171,24 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
struct mei_cl_cb *cb_pos,
struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
+ struct mei_cl_cb *cmpl_list)
{
if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
- sizeof(struct hbm_client_disconnect_request)))
+ sizeof(struct hbm_client_connect_request)))
return -EBADMSG;
- *slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request));
+ *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
if (mei_disconnect(dev, cl)) {
cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
+ cb_pos->buf_idx = 0;
+ list_move_tail(&cb_pos->list, &cmpl_list->list);
return -EMSGSIZE;
} else {
cl->state = MEI_FILE_DISCONNECTING;
cl->status = 0;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
+ cb_pos->buf_idx = 0;
+ list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
cl->timer_count = MEI_CONNECT_TIMEOUT;
}
@@ -356,7 +235,7 @@ static void mei_client_connect_response(struct mei_device *dev,
{
struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+ struct mei_cl_cb *pos = NULL, *next = NULL;
dev_dbg(&dev->pdev->dev,
"connect_response:\n"
@@ -373,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev,
dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
mei_watchdog_register(dev);
- /* next step in the state maching */
- mei_host_init_iamthif(dev);
return;
}
@@ -382,17 +259,16 @@ static void mei_client_connect_response(struct mei_device *dev,
dev->iamthif_state = MEI_IAMTHIF_IDLE;
return;
}
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
+ list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
- cl = (struct mei_cl *)cb_pos->file_private;
+ cl = pos->cl;
if (!cl) {
- list_del(&cb_pos->cb_list);
+ list_del(&pos->list);
return;
}
- if (MEI_IOCTL == cb_pos->major_file_operations) {
+ if (pos->fop_type == MEI_FOP_IOCTL) {
if (is_treat_specially_client(cl, rs)) {
- list_del(&cb_pos->cb_list);
+ list_del(&pos->list);
cl->status = 0;
cl->timer_count = 0;
break;
@@ -411,7 +287,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
struct hbm_client_connect_response *rs)
{
struct mei_cl *cl;
- struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
+ struct mei_cl_cb *pos = NULL, *next = NULL;
dev_dbg(&dev->pdev->dev,
"disconnect_response:\n"
@@ -422,12 +298,11 @@ static void mei_client_disconnect_response(struct mei_device *dev,
rs->host_addr,
rs->status);
- list_for_each_entry_safe(cb_pos, cb_next,
- &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
+ list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
+ cl = pos->cl;
if (!cl) {
- list_del(&cb_pos->cb_list);
+ list_del(&pos->list);
return;
}
@@ -435,7 +310,7 @@ static void mei_client_disconnect_response(struct mei_device *dev,
if (cl->host_client_id == rs->host_addr &&
cl->me_client_id == rs->me_addr) {
- list_del(&cb_pos->cb_list);
+ list_del(&pos->list);
if (!rs->status)
cl->state = MEI_FILE_DISCONNECTED;
@@ -537,10 +412,10 @@ static void mei_client_flow_control_response(struct mei_device *dev,
* returns !=0, same; 0,not.
*/
static int same_disconn_addr(struct mei_cl *cl,
- struct hbm_client_disconnect_request *disconn)
+ struct hbm_client_connect_request *req)
{
- return (cl->host_client_id == disconn->host_addr &&
- cl->me_client_id == disconn->me_addr);
+ return (cl->host_client_id == req->host_addr &&
+ cl->me_client_id == req->me_addr);
}
/**
@@ -550,49 +425,38 @@ static int same_disconn_addr(struct mei_cl *cl,
* @disconnect_req: disconnect request bus message.
*/
static void mei_client_disconnect_request(struct mei_device *dev,
- struct hbm_client_disconnect_request *disconnect_req)
+ struct hbm_client_connect_request *disconnect_req)
{
- struct mei_msg_hdr *mei_hdr;
struct hbm_client_connect_response *disconnect_res;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
+ struct mei_cl *pos, *next;
+ const size_t len = sizeof(struct hbm_client_connect_response);
- list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
- if (same_disconn_addr(cl_pos, disconnect_req)) {
+ list_for_each_entry_safe(pos, next, &dev->file_list, link) {
+ if (same_disconn_addr(pos, disconnect_req)) {
dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
disconnect_req->host_addr,
disconnect_req->me_addr);
- cl_pos->state = MEI_FILE_DISCONNECTED;
- cl_pos->timer_count = 0;
- if (cl_pos == &dev->wd_cl)
+ pos->state = MEI_FILE_DISCONNECTED;
+ pos->timer_count = 0;
+ if (pos == &dev->wd_cl)
dev->wd_pending = false;
- else if (cl_pos == &dev->iamthif_cl)
+ else if (pos == &dev->iamthif_cl)
dev->iamthif_timer = 0;
/* prepare disconnect response */
- mei_hdr =
- (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length =
- sizeof(struct hbm_client_connect_response);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
+ (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
disconnect_res =
(struct hbm_client_connect_response *)
- &dev->ext_msg_buf[1];
- disconnect_res->host_addr = cl_pos->host_client_id;
- disconnect_res->me_addr = cl_pos->me_client_id;
+ &dev->wr_ext_msg.data;
disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
+ disconnect_res->host_addr = pos->host_client_id;
+ disconnect_res->me_addr = pos->me_client_id;
disconnect_res->status = 0;
- dev->extra_write_index = 2;
break;
}
}
}
-
/**
* mei_irq_thread_read_bus_message - bottom half read routine after ISR to
* handle the read bus message cmd processing.
@@ -604,16 +468,15 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
struct mei_msg_hdr *mei_hdr)
{
struct mei_bus_message *mei_msg;
+ struct mei_me_client *me_client;
struct hbm_host_version_response *version_res;
struct hbm_client_connect_response *connect_res;
struct hbm_client_connect_response *disconnect_res;
+ struct hbm_client_connect_request *disconnect_req;
struct hbm_flow_control *flow_control;
struct hbm_props_response *props_res;
struct hbm_host_enum_response *enum_res;
- struct hbm_client_disconnect_request *disconnect_req;
- struct hbm_host_stop_request *host_stop_req;
- int res;
-
+ struct hbm_host_stop_request *stop_req;
/* read the message to our buffer */
BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
@@ -637,26 +500,20 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
return;
}
} else {
+ u32 *buf = dev->wr_msg_buf;
+ const size_t len = sizeof(struct hbm_host_stop_request);
+
dev->version = version_res->me_max_version;
+
/* send stop message */
- mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_stop_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- host_stop_req = (struct hbm_host_stop_request *)
- &dev->wr_msg_buf[1];
-
- memset(host_stop_req,
- 0,
- sizeof(struct hbm_host_stop_request));
- host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
- host_stop_req->reason = DRIVER_STOP_REQUEST;
+ mei_hdr = mei_hbm_hdr(&buf[0], len);
+ stop_req = (struct hbm_host_stop_request *)&buf[1];
+ memset(stop_req, 0, len);
+ stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
+ stop_req->reason = DRIVER_STOP_REQUEST;
+
mei_write_message(dev, mei_hdr,
- (unsigned char *) (host_stop_req),
- mei_hdr->length);
+ (unsigned char *)stop_req, len);
dev_dbg(&dev->pdev->dev, "version mismatch.\n");
return;
}
@@ -666,16 +523,14 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
break;
case CLIENT_CONNECT_RES_CMD:
- connect_res =
- (struct hbm_client_connect_response *) mei_msg;
+ connect_res = (struct hbm_client_connect_response *) mei_msg;
mei_client_connect_response(dev, connect_res);
dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
wake_up(&dev->wait_recvd_msg);
break;
case CLIENT_DISCONNECT_RES_CMD:
- disconnect_res =
- (struct hbm_client_connect_response *) mei_msg;
+ disconnect_res = (struct hbm_client_connect_response *) mei_msg;
mei_client_disconnect_response(dev, disconnect_res);
dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
wake_up(&dev->wait_recvd_msg);
@@ -689,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
case HOST_CLIENT_PROPERTIES_RES_CMD:
props_res = (struct hbm_props_response *)mei_msg;
+ me_client = &dev->me_clients[dev->me_client_presentation_num];
+
if (props_res->status || !dev->me_clients) {
dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
mei_reset(dev, 1);
return;
}
- if (dev->me_clients[dev->me_client_presentation_num]
- .client_id == props_res->address) {
- dev->me_clients[dev->me_client_presentation_num].props
- = props_res->client_properties;
+ if (me_client->client_id != props_res->address) {
+ dev_err(&dev->pdev->dev,
+ "Host client properties reply mismatch\n");
+ mei_reset(dev, 1);
- if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
- dev->init_clients_state ==
- MEI_CLIENT_PROPERTIES_MESSAGE) {
- dev->me_client_index++;
- dev->me_client_presentation_num++;
-
- /** Send Client Properties request **/
- res = mei_host_client_properties(dev);
- if (res < 0) {
- dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
- return;
- } else if (!res) {
- /*
- * No more clients to send to.
- * Clear Map for indicating now ME clients
- * with associated host client
- */
- bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
- dev->open_handle_count = 0;
-
- /*
- * Reserving the first three client IDs
- * Client Id 0 - Reserved for MEI Bus Message communications
- * Client Id 1 - Reserved for Watchdog
- * Client ID 2 - Reserved for AMTHI
- */
- bitmap_set(dev->host_clients_map, 0, 3);
- dev->dev_state = MEI_DEV_ENABLED;
-
- /* if wd initialization fails, initialization the AMTHI client,
- * otherwise the AMTHI client will be initialized after the WD client connect response
- * will be received
- */
- if (mei_wd_host_init(dev))
- mei_host_init_iamthif(dev);
- }
+ return;
+ }
- } else {
- dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
- mei_reset(dev, 1);
- return;
- }
- } else {
- dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
+ if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+ dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
+ dev_err(&dev->pdev->dev,
+ "Unexpected client properties reply\n");
mei_reset(dev, 1);
+
return;
}
+
+ me_client->props = props_res->client_properties;
+ dev->me_client_index++;
+ dev->me_client_presentation_num++;
+
+ mei_host_client_enumerate(dev);
+
break;
case HOST_ENUM_RES_CMD:
@@ -760,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
mei_allocate_me_clients_storage(dev);
dev->init_clients_state =
MEI_CLIENT_PROPERTIES_MESSAGE;
- mei_host_client_properties(dev);
+
+ mei_host_client_enumerate(dev);
} else {
dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
mei_reset(dev, 1);
@@ -776,29 +605,23 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
case CLIENT_DISCONNECT_REQ_CMD:
/* search for client */
- disconnect_req =
- (struct hbm_client_disconnect_request *) mei_msg;
+ disconnect_req = (struct hbm_client_connect_request *)mei_msg;
mei_client_disconnect_request(dev, disconnect_req);
break;
case ME_STOP_REQ_CMD:
- /* prepare stop request */
- mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
- mei_hdr->host_addr = 0;
- mei_hdr->me_addr = 0;
- mei_hdr->length = sizeof(struct hbm_host_stop_request);
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
- host_stop_req =
- (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
- memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
- host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
- host_stop_req->reason = DRIVER_STOP_REQUEST;
- host_stop_req->reserved[0] = 0;
- host_stop_req->reserved[1] = 0;
- dev->extra_write_index = 2;
- break;
+ {
+ /* prepare stop request: sent in next interrupt event */
+
+ const size_t len = sizeof(struct hbm_host_stop_request);
+ mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
+ stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
+ memset(stop_req, 0, len);
+ stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
+ stop_req->reason = DRIVER_STOP_REQUEST;
+ break;
+ }
default:
BUG();
break;
@@ -821,12 +644,12 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
struct mei_cl_cb *cb_pos,
struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
+ struct mei_cl_cb *cmpl_list)
{
if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_flow_control))) {
/* return the cancel routine */
- list_del(&cb_pos->cb_list);
+ list_del(&cb_pos->list);
return -EBADMSG;
}
@@ -834,11 +657,11 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
if (mei_send_flow_control(dev, cl)) {
cl->status = -ENODEV;
- cb_pos->information = 0;
- list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
+ cb_pos->buf_idx = 0;
+ list_move_tail(&cb_pos->list, &cmpl_list->list);
return -ENODEV;
}
- list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
+ list_move_tail(&cb_pos->list, &dev->read_list.list);
return 0;
}
@@ -858,12 +681,12 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
struct mei_cl_cb *cb_pos,
struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
+ struct mei_cl_cb *cmpl_list)
{
if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
sizeof(struct hbm_client_connect_request))) {
/* return the cancel routine */
- list_del(&cb_pos->cb_list);
+ list_del(&cb_pos->list);
return -EBADMSG;
}
@@ -871,188 +694,73 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
*slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
if (mei_connect(dev, cl)) {
cl->status = -ENODEV;
- cb_pos->information = 0;
- list_del(&cb_pos->cb_list);
+ cb_pos->buf_idx = 0;
+ list_del(&cb_pos->list);
return -ENODEV;
} else {
- list_move_tail(&cb_pos->cb_list,
- &dev->ctrl_rd_list.mei_cb.cb_list);
+ list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
cl->timer_count = MEI_CONNECT_TIMEOUT;
}
return 0;
}
/**
- * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
+ * mei_irq_thread_write_complete - write messages to device.
*
* @dev: the device structure.
* @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
+ * @cb: callback block.
* @cmpl_list: complete list.
*
* returns 0, OK; otherwise, error.
*/
-static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
+static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
+ struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
{
struct mei_msg_hdr *mei_hdr;
+ struct mei_cl *cl = cb->cl;
+ size_t len = cb->request_buffer.size - cb->buf_idx;
+ size_t msg_slots = mei_data2slots(len);
+
+ mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
+ mei_hdr->host_addr = cl->host_client_id;
+ mei_hdr->me_addr = cl->me_client_id;
+ mei_hdr->reserved = 0;
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- (cb_pos->request_buffer.size -
- cb_pos->information))) {
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length = cb_pos->request_buffer.size -
- cb_pos->information;
+ if (*slots >= msg_slots) {
+ mei_hdr->length = len;
mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
- dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
- "mei_hdr->msg_complete = %d\n",
- cb_pos->request_buffer.size,
- mei_hdr->msg_complete);
- dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
- cb_pos->information);
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
- mei_hdr->length);
- *slots -= mei_data2slots(mei_hdr->length);
- if (mei_write_message(dev, mei_hdr,
- (unsigned char *)
- (cb_pos->request_buffer.data +
- cb_pos->information),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -ENODEV;
- } else {
- if (mei_flow_ctrl_reduce(dev, cl))
- return -ENODEV;
- cl->status = 0;
- cb_pos->information += mei_hdr->length;
- list_move_tail(&cb_pos->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- }
+ /* Split the message only if we can write the whole host buffer */
} else if (*slots == dev->hbuf_depth) {
- /* buffer is still empty */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length =
- (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+ msg_slots = *slots;
+ len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+ mei_hdr->length = len;
mei_hdr->msg_complete = 0;
- mei_hdr->reserved = 0;
- *slots -= mei_data2slots(mei_hdr->length);
- if (mei_write_message(dev, mei_hdr,
- (unsigned char *)
- (cb_pos->request_buffer.data +
- cb_pos->information),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_move_tail(&cb_pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
- return -ENODEV;
- } else {
- cb_pos->information += mei_hdr->length;
- dev_dbg(&dev->pdev->dev,
- "cb_pos->request_buffer.size =%d"
- " mei_hdr->msg_complete = %d\n",
- cb_pos->request_buffer.size,
- mei_hdr->msg_complete);
- dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
- cb_pos->information);
- dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
- mei_hdr->length);
- }
- return -EMSGSIZE;
} else {
- return -EBADMSG;
+ /* wait for next time the host buffer is empty */
+ return 0;
}
- return 0;
-}
-
-/**
- * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
- struct mei_cl_cb *cb_pos,
- struct mei_cl *cl,
- struct mei_io_list *cmpl_list)
-{
- struct mei_msg_hdr *mei_hdr;
-
- if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
- dev->iamthif_msg_buf_size -
- dev->iamthif_msg_buf_index)) {
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length = dev->iamthif_msg_buf_size -
- dev->iamthif_msg_buf_index;
- mei_hdr->msg_complete = 1;
- mei_hdr->reserved = 0;
-
- *slots -= mei_data2slots(mei_hdr->length);
-
- if (mei_write_message(dev, mei_hdr,
- (dev->iamthif_msg_buf +
- dev->iamthif_msg_buf_index),
- mei_hdr->length)) {
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- cl->status = -ENODEV;
- list_del(&cb_pos->cb_list);
- return -ENODEV;
- } else {
- if (mei_flow_ctrl_reduce(dev, cl))
- return -ENODEV;
- dev->iamthif_msg_buf_index += mei_hdr->length;
- cb_pos->information = dev->iamthif_msg_buf_index;
- cl->status = 0;
- dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
- dev->iamthif_flow_control_pending = true;
- /* save iamthif cb sent to amthi client */
- dev->iamthif_current_cb = cb_pos;
- list_move_tail(&cb_pos->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
+ dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
+ cb->request_buffer.size, cb->buf_idx);
+ dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
+ mei_hdr->length, mei_hdr->msg_complete);
- }
- } else if (*slots == dev->hbuf_depth) {
- /* buffer is still empty */
- mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
- mei_hdr->host_addr = cl->host_client_id;
- mei_hdr->me_addr = cl->me_client_id;
- mei_hdr->length =
- (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
- mei_hdr->msg_complete = 0;
- mei_hdr->reserved = 0;
+ *slots -= msg_slots;
+ if (mei_write_message(dev, mei_hdr,
+ cb->request_buffer.data + cb->buf_idx, len)) {
+ cl->status = -ENODEV;
+ list_move_tail(&cb->list, &cmpl_list->list);
+ return -ENODEV;
+ }
- *slots -= mei_data2slots(mei_hdr->length);
+ if (mei_flow_ctrl_reduce(dev, cl))
+ return -ENODEV;
- if (mei_write_message(dev, mei_hdr,
- (dev->iamthif_msg_buf +
- dev->iamthif_msg_buf_index),
- mei_hdr->length)) {
- cl->status = -ENODEV;
- list_del(&cb_pos->cb_list);
- } else {
- dev->iamthif_msg_buf_index += mei_hdr->length;
- }
- return -EMSGSIZE;
- } else {
- return -EBADMSG;
- }
+ cl->status = 0;
+ cb->buf_idx += mei_hdr->length;
+ if (mei_hdr->msg_complete)
+ list_move_tail(&cb->list, &dev->write_waiting_list.list);
return 0;
}
@@ -1067,7 +775,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
*
* returns 0 on success, <0 on failure.
*/
-static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
+static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
struct mei_device *dev,
s32 *slots)
{
@@ -1130,8 +838,8 @@ static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
mei_hdr->length);
- ret = mei_irq_thread_read_amthi_message(cmpl_list,
- dev, mei_hdr);
+
+ ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
if (ret)
goto end;
@@ -1164,53 +872,51 @@ end:
* mei_irq_thread_write_handler - bottom half write routine after
* ISR to handle the write processing.
*
- * @cmpl_list: An instance of our list structure
* @dev: the device structure
- * @slots: slots to write.
+ * @cmpl_list: An instance of our list structure
*
* returns 0 on success, <0 on failure.
*/
-static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
- struct mei_device *dev,
- s32 *slots)
+static int mei_irq_thread_write_handler(struct mei_device *dev,
+ struct mei_cl_cb *cmpl_list)
{
struct mei_cl *cl;
struct mei_cl_cb *pos = NULL, *next = NULL;
- struct mei_io_list *list;
+ struct mei_cl_cb *list;
+ s32 slots;
int ret;
if (!mei_hbuf_is_empty(dev)) {
dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
return 0;
}
- *slots = mei_hbuf_empty_slots(dev);
- if (*slots <= 0)
+ slots = mei_hbuf_empty_slots(dev);
+ if (slots <= 0)
return -EMSGSIZE;
/* complete all waiting for write CB */
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
list = &dev->write_waiting_list;
- list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)pos->file_private;
+ list_for_each_entry_safe(pos, next, &list->list, list) {
+ cl = pos->cl;
if (cl == NULL)
continue;
cl->status = 0;
- list_del(&pos->cb_list);
+ list_del(&pos->list);
if (MEI_WRITING == cl->writing_state &&
- (pos->major_file_operations == MEI_WRITE) &&
- (cl != &dev->iamthif_cl)) {
+ pos->fop_type == MEI_FOP_WRITE &&
+ cl != &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
cl->writing_state = MEI_WRITE_COMPLETE;
- list_add_tail(&pos->cb_list,
- &cmpl_list->mei_cb.cb_list);
+ list_add_tail(&pos->list, &cmpl_list->list);
}
if (cl == &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
if (dev->iamthif_flow_control_pending) {
- ret = _mei_irq_thread_iamthif_read(dev, slots);
+ ret = mei_amthif_irq_read(dev, &slots);
if (ret)
return ret;
}
@@ -1222,15 +928,11 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
wake_up_interruptible(&dev->wait_stop_wd);
}
- if (dev->extra_write_index) {
- dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
- dev->extra_write_index);
- mei_write_message(dev,
- (struct mei_msg_hdr *) &dev->ext_msg_buf[0],
- (unsigned char *) &dev->ext_msg_buf[1],
- (dev->extra_write_index - 1) * sizeof(u32));
- *slots -= dev->extra_write_index;
- dev->extra_write_index = 0;
+ if (dev->wr_ext_msg.hdr.length) {
+ mei_write_message(dev, &dev->wr_ext_msg.hdr,
+ dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length);
+ slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
+ dev->wr_ext_msg.hdr.length = 0;
}
if (dev->dev_state == MEI_DEV_ENABLED) {
if (dev->wd_pending &&
@@ -1243,41 +945,43 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
dev->wd_pending = false;
if (dev->wd_state == MEI_WD_RUNNING)
- *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
+ slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
else
- *slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
+ slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
}
}
/* complete control write list CB */
dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
- list_for_each_entry_safe(pos, next,
- &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *) pos->file_private;
+ list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
+ cl = pos->cl;
if (!cl) {
- list_del(&pos->cb_list);
+ list_del(&pos->list);
return -ENODEV;
}
- switch (pos->major_file_operations) {
- case MEI_CLOSE:
+ switch (pos->fop_type) {
+ case MEI_FOP_CLOSE:
/* send disconnect message */
- ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list);
+ ret = _mei_irq_thread_close(dev, &slots, pos,
+ cl, cmpl_list);
if (ret)
return ret;
break;
- case MEI_READ:
+ case MEI_FOP_READ:
/* send flow control message */
- ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list);
+ ret = _mei_irq_thread_read(dev, &slots, pos,
+ cl, cmpl_list);
if (ret)
return ret;
break;
- case MEI_IOCTL:
+ case MEI_FOP_IOCTL:
/* connect message */
if (mei_other_client_is_connecting(dev, cl))
continue;
- ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list);
+ ret = _mei_irq_thread_ioctl(dev, &slots, pos,
+ cl, cmpl_list);
if (ret)
return ret;
@@ -1290,40 +994,26 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
}
/* complete write list CB */
dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
- list_for_each_entry_safe(pos, next,
- &dev->write_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)pos->file_private;
+ list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
+ cl = pos->cl;
if (cl == NULL)
continue;
-
- if (cl != &dev->iamthif_cl) {
- if (mei_flow_ctrl_creds(dev, cl) <= 0) {
- dev_dbg(&dev->pdev->dev,
- "No flow control credentials for client %d, not sending.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl(dev, slots, pos,
- cl, cmpl_list);
- if (ret)
- return ret;
-
- } else if (cl == &dev->iamthif_cl) {
- /* IAMTHIF IOCTL */
- dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
- if (mei_flow_ctrl_creds(dev, cl) <= 0) {
- dev_dbg(&dev->pdev->dev,
- "No flow control credentials for amthi client %d.\n",
- cl->host_client_id);
- continue;
- }
- ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos,
- cl, cmpl_list);
- if (ret)
- return ret;
-
+ if (mei_flow_ctrl_creds(dev, cl) <= 0) {
+ dev_dbg(&dev->pdev->dev,
+ "No flow control credentials for client %d, not sending.\n",
+ cl->host_client_id);
+ continue;
}
+ if (cl == &dev->iamthif_cl)
+ ret = mei_amthif_irq_write_complete(dev, &slots,
+ pos, cmpl_list);
+ else
+ ret = mei_irq_thread_write_complete(dev, &slots, pos,
+ cmpl_list);
+ if (ret)
+ return ret;
+
}
return 0;
}
@@ -1342,7 +1032,6 @@ void mei_timer(struct work_struct *work)
unsigned long timeout;
struct mei_cl *cl_pos = NULL;
struct mei_cl *cl_next = NULL;
- struct list_head *amthi_complete_list = NULL;
struct mei_cl_cb *cb_pos = NULL;
struct mei_cl_cb *cb_next = NULL;
@@ -1385,19 +1074,18 @@ void mei_timer(struct work_struct *work)
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
- if (dev->iamthif_current_cb)
- mei_free_cb_private(dev->iamthif_current_cb);
+ mei_io_cb_free(dev->iamthif_current_cb);
+ dev->iamthif_current_cb = NULL;
dev->iamthif_file_object = NULL;
- dev->iamthif_current_cb = NULL;
- mei_run_next_iamthif_cmd(dev);
+ mei_amthif_run_next_cmd(dev);
}
}
if (dev->iamthif_timer) {
timeout = dev->iamthif_timer +
- msecs_to_jiffies(IAMTHIF_READ_TIMER);
+ mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
dev->iamthif_timer);
@@ -1411,25 +1099,22 @@ void mei_timer(struct work_struct *work)
dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
- amthi_complete_list = &dev->amthi_read_complete_list.
- mei_cb.cb_list;
-
- list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
+ list_for_each_entry_safe(cb_pos, cb_next,
+ &dev->amthif_rd_complete_list.list, list) {
cl_pos = cb_pos->file_object->private_data;
/* Finding the AMTHI entry. */
if (cl_pos == &dev->iamthif_cl)
- list_del(&cb_pos->cb_list);
+ list_del(&cb_pos->list);
}
- if (dev->iamthif_current_cb)
- mei_free_cb_private(dev->iamthif_current_cb);
+ mei_io_cb_free(dev->iamthif_current_cb);
+ dev->iamthif_current_cb = NULL;
dev->iamthif_file_object->private_data = NULL;
dev->iamthif_file_object = NULL;
- dev->iamthif_current_cb = NULL;
dev->iamthif_timer = 0;
- mei_run_next_iamthif_cmd(dev);
+ mei_amthif_run_next_cmd(dev);
}
}
@@ -1451,7 +1136,7 @@ out:
irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
{
struct mei_device *dev = (struct mei_device *) dev_id;
- struct mei_io_list complete_list;
+ struct mei_cl_cb complete_list;
struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
struct mei_cl *cl;
s32 slots;
@@ -1504,17 +1189,17 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
}
/* check slots available for reading */
slots = mei_count_full_read_slots(dev);
- dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
- slots, dev->extra_write_index);
- while (slots > 0 && !dev->extra_write_index) {
- dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
- slots, dev->extra_write_index);
+ while (slots > 0) {
+ /* we have urgent data to send so break the read */
+ if (dev->wr_ext_msg.hdr.length)
+ break;
+ dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
if (rets)
goto end;
}
- rets = mei_irq_thread_write_handler(&complete_list, dev, &slots);
+ rets = mei_irq_thread_write_handler(dev, &complete_list);
end:
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
dev->host_hw_state = mei_hcsr_read(dev);
@@ -1531,21 +1216,20 @@ end:
wake_up_interruptible(&dev->wait_recvd_msg);
bus_message_received = false;
}
- if (list_empty(&complete_list.mei_cb.cb_list))
+ if (list_empty(&complete_list.list))
return IRQ_HANDLED;
- list_for_each_entry_safe(cb_pos, cb_next,
- &complete_list.mei_cb.cb_list, cb_list) {
- cl = (struct mei_cl *)cb_pos->file_private;
- list_del(&cb_pos->cb_list);
+ list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
+ cl = cb_pos->cl;
+ list_del(&cb_pos->list);
if (cl) {
if (cl != &dev->iamthif_cl) {
dev_dbg(&dev->pdev->dev, "completing call back.\n");
_mei_cmpl(cl, cb_pos);
cb_pos = NULL;
} else if (cl == &dev->iamthif_cl) {
- _mei_cmpl_iamthif(dev, cb_pos);
+ mei_amthif_complete(dev, cb_pos);
}
}
}
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c
index fcba98eb892e..eb93a1b53b9b 100644
--- a/drivers/misc/mei/iorw.c
+++ b/drivers/misc/mei/iorw.c
@@ -39,6 +39,95 @@
#include "interface.h"
/**
+ * mei_io_cb_free - free mei_cb_private related memory
+ *
+ * @cb: mei callback struct
+ */
+void mei_io_cb_free(struct mei_cl_cb *cb)
+{
+ if (cb == NULL)
+ return;
+
+ kfree(cb->request_buffer.data);
+ kfree(cb->response_buffer.data);
+ kfree(cb);
+}
+/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl - mei client
+ * @file: pointer to file structure
+ *
+ * returns mei_cl_cb pointer or NULL;
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+{
+ struct mei_cl_cb *cb;
+
+ cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ if (!cb)
+ return NULL;
+
+ mei_io_list_init(cb);
+
+ cb->file_object = fp;
+ cb->cl = cl;
+ cb->buf_idx = 0;
+ return cb;
+}
+
+
+/**
+ * mei_io_cb_alloc_req_buf - allocate request buffer
+ *
+ * @cb - io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ * -EINVAL if cb is NULL
+ * -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+{
+ if (!cb)
+ return -EINVAL;
+
+ if (length == 0)
+ return 0;
+
+ cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
+ if (!cb->request_buffer.data)
+ return -ENOMEM;
+ cb->request_buffer.size = length;
+ return 0;
+}
+/**
+ * mei_io_cb_alloc_req_buf - allocate respose buffer
+ *
+ * @cb - io callback structure
+ * @size: size of the buffer
+ *
+ * returns 0 on success
+ * -EINVAL if cb is NULL
+ * -ENOMEM if allocation failed
+ */
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
+{
+ if (!cb)
+ return -EINVAL;
+
+ if (length == 0)
+ return 0;
+
+ cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
+ if (!cb->response_buffer.data)
+ return -ENOMEM;
+ cb->response_buffer.size = length;
+ return 0;
+}
+
+
+/**
* mei_me_cl_by_id return index to me_clients for client_id
*
* @dev: the device structure
@@ -82,9 +171,7 @@ int mei_ioctl_connect_client(struct file *file,
struct mei_cl_cb *cb;
struct mei_client *client;
struct mei_cl *cl;
- struct mei_cl *cl_pos = NULL;
- struct mei_cl *cl_next = NULL;
- long timeout = CONNECT_TIMEOUT;
+ long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
int i;
int err;
int rets;
@@ -97,16 +184,14 @@ int mei_ioctl_connect_client(struct file *file,
dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
-
/* buffered ioctl cb */
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ cb = mei_io_cb_init(cl, file);
if (!cb) {
rets = -ENOMEM;
goto end;
}
- INIT_LIST_HEAD(&cb->cb_list);
- cb->major_file_operations = MEI_IOCTL;
+ cb->fop_type = MEI_FOP_IOCTL;
if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV;
@@ -142,21 +227,9 @@ int mei_ioctl_connect_client(struct file *file,
goto end;
}
clear_bit(cl->host_client_id, dev->host_clients_map);
- list_for_each_entry_safe(cl_pos, cl_next,
- &dev->file_list, link) {
- if (mei_cl_cmp_id(cl, cl_pos)) {
- dev_dbg(&dev->pdev->dev,
- "remove file private data node host"
- " client = %d, ME client = %d.\n",
- cl_pos->host_client_id,
- cl_pos->me_client_id);
- list_del(&cl_pos->link);
- }
+ mei_me_cl_unlink(dev, cl);
- }
- dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
kfree(cl);
-
cl = NULL;
file->private_data = &dev->iamthif_cl;
@@ -192,25 +265,19 @@ int mei_ioctl_connect_client(struct file *file,
} else {
dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
cl->timer_count = MEI_CONNECT_TIMEOUT;
- cb->file_private = cl;
- list_add_tail(&cb->cb_list,
- &dev->ctrl_rd_list.mei_cb.
- cb_list);
+ list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
}
} else {
dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
- cb->file_private = cl;
dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
- list_add_tail(&cb->cb_list,
- &dev->ctrl_wr_list.mei_cb.cb_list);
+ list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
mutex_unlock(&dev->device_lock);
err = wait_event_timeout(dev->wait_recvd_msg,
(MEI_FILE_CONNECTED == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state),
- timeout * HZ);
+ MEI_FILE_DISCONNECTED == cl->state), timeout);
mutex_lock(&dev->device_lock);
if (MEI_FILE_CONNECTED == cl->state) {
@@ -234,153 +301,7 @@ int mei_ioctl_connect_client(struct file *file,
rets = 0;
end:
dev_dbg(&dev->pdev->dev, "free connect cb memory.");
- kfree(cb);
- return rets;
-}
-
-/**
- * find_amthi_read_list_entry - finds a amthilist entry for current file
- *
- * @dev: the device structure
- * @file: pointer to file object
- *
- * returns returned a list entry on success, NULL on failure.
- */
-struct mei_cl_cb *find_amthi_read_list_entry(
- struct mei_device *dev,
- struct file *file)
-{
- struct mei_cl *cl_temp;
- struct mei_cl_cb *pos = NULL;
- struct mei_cl_cb *next = NULL;
-
- list_for_each_entry_safe(pos, next,
- &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
- cl_temp = (struct mei_cl *)pos->file_private;
- if (cl_temp && cl_temp == &dev->iamthif_cl &&
- pos->file_object == file)
- return pos;
- }
- return NULL;
-}
-
-/**
- * amthi_read - read data from AMTHI client
- *
- * @dev: the device structure
- * @if_num: minor number
- * @file: pointer to file object
- * @*ubuf: pointer to user data in user space
- * @length: data length to read
- * @offset: data read offset
- *
- * Locking: called under "dev->device_lock" lock
- *
- * returns
- * returned data length on success,
- * zero if no data to read,
- * negative on failure.
- */
-int amthi_read(struct mei_device *dev, struct file *file,
- char __user *ubuf, size_t length, loff_t *offset)
-{
- int rets;
- int wait_ret;
- struct mei_cl_cb *cb = NULL;
- struct mei_cl *cl = file->private_data;
- unsigned long timeout;
- int i;
-
- /* Only Posible if we are in timeout */
- if (!cl || cl != &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "bad file ext.\n");
- return -ETIMEDOUT;
- }
-
- i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
-
- if (i < 0) {
- dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
- return -ENODEV;
- }
- dev_dbg(&dev->pdev->dev, "checking amthi data\n");
- cb = find_amthi_read_list_entry(dev, file);
-
- /* Check for if we can block or not*/
- if (cb == NULL && file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
-
- dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
- while (cb == NULL) {
- /* unlock the Mutex */
- mutex_unlock(&dev->device_lock);
-
- wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
- (cb = find_amthi_read_list_entry(dev, file)));
-
- if (wait_ret)
- return -ERESTARTSYS;
-
- dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
-
- /* Locking again the Mutex */
- mutex_lock(&dev->device_lock);
- }
-
-
- dev_dbg(&dev->pdev->dev, "Got amthi data\n");
- dev->iamthif_timer = 0;
-
- if (cb) {
- timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
- dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
- timeout);
-
- if (time_after(jiffies, timeout)) {
- dev_dbg(&dev->pdev->dev, "amthi Time out\n");
- /* 15 sec for the message has expired */
- list_del(&cb->cb_list);
- rets = -ETIMEDOUT;
- goto free;
- }
- }
- /* if the whole message will fit remove it from the list */
- if (cb->information >= *offset && length >= (cb->information - *offset))
- list_del(&cb->cb_list);
- else if (cb->information > 0 && cb->information <= *offset) {
- /* end of the message has been reached */
- list_del(&cb->cb_list);
- rets = 0;
- goto free;
- }
- /* else means that not full buffer will be read and do not
- * remove message from deletion list
- */
-
- dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
- cb->response_buffer.size);
- dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
- cb->information);
-
- /* length is being turncated to PAGE_SIZE, however,
- * the information may be longer */
- length = min_t(size_t, length, (cb->information - *offset));
-
- if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
- rets = -EFAULT;
- else {
- rets = length;
- if ((*offset + length) < cb->information) {
- *offset += length;
- goto out;
- }
- }
-free:
- dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
- *offset = 0;
- mei_free_cb_private(cb);
-out:
+ mei_io_cb_free(cb);
return rets;
}
@@ -396,7 +317,7 @@ out:
int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
{
struct mei_cl_cb *cb;
- int rets = 0;
+ int rets;
int i;
if (cl->state != MEI_FILE_CONNECTED)
@@ -405,187 +326,41 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
if (dev->dev_state != MEI_DEV_ENABLED)
return -ENODEV;
- dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
if (cl->read_pending || cl->read_cb) {
dev_dbg(&dev->pdev->dev, "read is pending.\n");
return -EBUSY;
}
+ i = mei_me_cl_by_id(dev, cl->me_client_id);
+ if (i < 0) {
+ dev_err(&dev->pdev->dev, "no such me client %d\n",
+ cl->me_client_id);
+ return -ENODEV;
+ }
- cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ cb = mei_io_cb_init(cl, NULL);
if (!cb)
return -ENOMEM;
- dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
- cl->host_client_id, cl->me_client_id);
- i = mei_me_cl_by_id(dev, cl->me_client_id);
- if (i < 0) {
- rets = -ENODEV;
- goto unlock;
- }
+ rets = mei_io_cb_alloc_resp_buf(cb,
+ dev->me_clients[i].props.max_msg_length);
+ if (rets)
+ goto err;
- cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
- cb->response_buffer.data =
- kmalloc(cb->response_buffer.size, GFP_KERNEL);
- if (!cb->response_buffer.data) {
- rets = -ENOMEM;
- goto unlock;
- }
- dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
- cb->major_file_operations = MEI_READ;
- /* make sure information is zero before we start */
- cb->information = 0;
- cb->file_private = (void *) cl;
+ cb->fop_type = MEI_FOP_READ;
cl->read_cb = cb;
if (dev->mei_host_buffer_is_empty) {
dev->mei_host_buffer_is_empty = false;
if (mei_send_flow_control(dev, cl)) {
rets = -ENODEV;
- goto unlock;
+ goto err;
}
- list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
+ list_add_tail(&cb->list, &dev->read_list.list);
} else {
- list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
+ list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
return rets;
-unlock:
- mei_free_cb_private(cb);
+err:
+ mei_io_cb_free(cb);
return rets;
}
-/**
- * amthi_write - write iamthif data to amthi client
- *
- * @dev: the device structure
- * @cb: mei call back struct
- *
- * returns 0 on success, <0 on failure.
- */
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
-{
- struct mei_msg_hdr mei_hdr;
- int ret;
-
- if (!dev || !cb)
- return -ENODEV;
-
- dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
-
- dev->iamthif_state = MEI_IAMTHIF_WRITING;
- dev->iamthif_current_cb = cb;
- dev->iamthif_file_object = cb->file_object;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = true;
- dev->iamthif_msg_buf_size = cb->request_buffer.size;
- memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
- cb->request_buffer.size);
-
- ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
- if (ret < 0)
- return ret;
-
- if (ret && dev->mei_host_buffer_is_empty) {
- ret = 0;
- dev->mei_host_buffer_is_empty = false;
- if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
- mei_hdr.length = mei_hbuf_max_data(dev);
- mei_hdr.msg_complete = 0;
- } else {
- mei_hdr.length = cb->request_buffer.size;
- mei_hdr.msg_complete = 1;
- }
-
- mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
- mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
- mei_hdr.reserved = 0;
- dev->iamthif_msg_buf_index += mei_hdr.length;
- if (mei_write_message(dev, &mei_hdr,
- (unsigned char *)(dev->iamthif_msg_buf),
- mei_hdr.length))
- return -ENODEV;
-
- if (mei_hdr.msg_complete) {
- if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
- return -ENODEV;
- dev->iamthif_flow_control_pending = true;
- dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
- dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
- dev->iamthif_current_cb = cb;
- dev->iamthif_file_object = cb->file_object;
- list_add_tail(&cb->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- } else {
- dev_dbg(&dev->pdev->dev, "message does not complete, "
- "so add amthi cb to write list.\n");
- list_add_tail(&cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
- }
- } else {
- if (!(dev->mei_host_buffer_is_empty))
- dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
- dev_dbg(&dev->pdev->dev, "No flow control credentials, "
- "so add iamthif cb to write list.\n");
- list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
- }
- return 0;
-}
-
-/**
- * iamthif_ioctl_send_msg - send cmd data to amthi client
- *
- * @dev: the device structure
- *
- * returns 0 on success, <0 on failure.
- */
-void mei_run_next_iamthif_cmd(struct mei_device *dev)
-{
- struct mei_cl *cl_tmp;
- struct mei_cl_cb *pos = NULL;
- struct mei_cl_cb *next = NULL;
- int status;
-
- if (!dev)
- return;
-
- dev->iamthif_msg_buf_size = 0;
- dev->iamthif_msg_buf_index = 0;
- dev->iamthif_canceled = false;
- dev->iamthif_ioctl = true;
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- dev->iamthif_timer = 0;
- dev->iamthif_file_object = NULL;
-
- dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
-
- list_for_each_entry_safe(pos, next,
- &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
- list_del(&pos->cb_list);
- cl_tmp = (struct mei_cl *)pos->file_private;
-
- if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
- status = amthi_write(dev, pos);
- if (status) {
- dev_dbg(&dev->pdev->dev,
- "amthi write failed status = %d\n",
- status);
- return;
- }
- break;
- }
- }
-}
-
-/**
- * mei_free_cb_private - free mei_cb_private related memory
- *
- * @cb: mei callback struct
- */
-void mei_free_cb_private(struct mei_cl_cb *cb)
-{
- if (cb == NULL)
- return;
-
- kfree(cb->request_buffer.data);
- kfree(cb->response_buffer.data);
- kfree(cb);
-}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index e8b0858132c1..43fb52ff98ad 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -90,93 +90,6 @@ static DEFINE_MUTEX(mei_mutex);
/**
- * mei_clear_list - removes all callbacks associated with file
- * from mei_cb_list
- *
- * @dev: device structure.
- * @file: file structure
- * @mei_cb_list: callbacks list
- *
- * mei_clear_list is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_list(struct mei_device *dev,
- struct file *file, struct list_head *mei_cb_list)
-{
- struct mei_cl_cb *cb_pos = NULL;
- struct mei_cl_cb *cb_next = NULL;
- struct file *file_temp;
- bool removed = false;
-
- /* list all list member */
- list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
- file_temp = (struct file *)cb_pos->file_object;
- /* check if list member associated with a file */
- if (file_temp == file) {
- /* remove member from the list */
- list_del(&cb_pos->cb_list);
- /* check if cb equal to current iamthif cb */
- if (dev->iamthif_current_cb == cb_pos) {
- dev->iamthif_current_cb = NULL;
- /* send flow control to iamthif client */
- mei_send_flow_control(dev, &dev->iamthif_cl);
- }
- /* free all allocated buffers */
- mei_free_cb_private(cb_pos);
- cb_pos = NULL;
- removed = true;
- }
- }
- return removed;
-}
-
-/**
- * mei_clear_lists - removes all callbacks associated with file
- *
- * @dev: device structure
- * @file: file structure
- *
- * mei_clear_lists is called to clear resources associated with file
- * when application calls close function or Ctrl-C was pressed
- *
- * returns true if callback removed from the list, false otherwise
- */
-static bool mei_clear_lists(struct mei_device *dev, struct file *file)
-{
- bool removed = false;
-
- /* remove callbacks associated with a file */
- mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
- if (mei_clear_list(dev, file,
- &dev->amthi_read_complete_list.mei_cb.cb_list))
- removed = true;
-
- mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
-
- if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
- removed = true;
-
- if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
- removed = true;
-
- if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
- removed = true;
-
- /* check if iamthif_current_cb not NULL */
- if (dev->iamthif_current_cb && !removed) {
- /* check file and iamthif current cb association */
- if (dev->iamthif_current_cb->file_object == file) {
- /* remove cb */
- mei_free_cb_private(dev->iamthif_current_cb);
- dev->iamthif_current_cb = NULL;
- removed = true;
- }
- }
- return removed;
-}
-/**
* find_read_list_entry - find read list entry
*
* @dev: device structure
@@ -192,14 +105,9 @@ static struct mei_cl_cb *find_read_list_entry(
struct mei_cl_cb *next = NULL;
dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
- list_for_each_entry_safe(pos, next,
- &dev->read_list.mei_cb.cb_list, cb_list) {
- struct mei_cl *cl_temp;
- cl_temp = (struct mei_cl *)pos->file_private;
-
- if (mei_cl_cmp_id(cl, cl_temp))
+ list_for_each_entry_safe(pos, next, &dev->read_list.list, list)
+ if (mei_cl_cmp_id(cl, pos->cl))
return pos;
- }
return NULL;
}
@@ -297,67 +205,51 @@ static int mei_release(struct inode *inode, struct file *file)
dev = cl->dev;
mutex_lock(&dev->device_lock);
- if (cl != &dev->iamthif_cl) {
- if (cl->state == MEI_FILE_CONNECTED) {
- cl->state = MEI_FILE_DISCONNECTING;
- dev_dbg(&dev->pdev->dev,
- "disconnecting client host client = %d, "
- "ME client = %d\n",
- cl->host_client_id,
- cl->me_client_id);
- rets = mei_disconnect_host_client(dev, cl);
- }
- mei_cl_flush_queues(cl);
- dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
+ if (cl == &dev->iamthif_cl) {
+ rets = mei_amthif_release(dev, file);
+ goto out;
+ }
+ if (cl->state == MEI_FILE_CONNECTED) {
+ cl->state = MEI_FILE_DISCONNECTING;
+ dev_dbg(&dev->pdev->dev,
+ "disconnecting client host client = %d, "
+ "ME client = %d\n",
cl->host_client_id,
cl->me_client_id);
+ rets = mei_disconnect_host_client(dev, cl);
+ }
+ mei_cl_flush_queues(cl);
+ dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
+ cl->host_client_id,
+ cl->me_client_id);
+
+ if (dev->open_handle_count > 0) {
+ clear_bit(cl->host_client_id, dev->host_clients_map);
+ dev->open_handle_count--;
+ }
+ mei_me_cl_unlink(dev, cl);
- if (dev->open_handle_count > 0) {
- clear_bit(cl->host_client_id, dev->host_clients_map);
- dev->open_handle_count--;
- }
- mei_remove_client_from_file_list(dev, cl->host_client_id);
-
- /* free read cb */
- cb = NULL;
- if (cl->read_cb) {
- cb = find_read_list_entry(dev, cl);
- /* Remove entry from read list */
- if (cb)
- list_del(&cb->cb_list);
-
- cb = cl->read_cb;
- cl->read_cb = NULL;
- }
-
- file->private_data = NULL;
-
- if (cb) {
- mei_free_cb_private(cb);
- cb = NULL;
- }
+ /* free read cb */
+ cb = NULL;
+ if (cl->read_cb) {
+ cb = find_read_list_entry(dev, cl);
+ /* Remove entry from read list */
+ if (cb)
+ list_del(&cb->list);
- kfree(cl);
- } else {
- if (dev->open_handle_count > 0)
- dev->open_handle_count--;
-
- if (dev->iamthif_file_object == file &&
- dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-
- dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
- dev->iamthif_state);
- dev->iamthif_canceled = true;
- if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
- dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
- mei_run_next_iamthif_cmd(dev);
- }
- }
+ cb = cl->read_cb;
+ cl->read_cb = NULL;
+ }
- if (mei_clear_lists(dev, file))
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ file->private_data = NULL;
+ if (cb) {
+ mei_io_cb_free(cb);
+ cb = NULL;
}
+
+ kfree(cl);
+out:
mutex_unlock(&dev->device_lock);
return rets;
}
@@ -411,20 +303,19 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
}
if (cl == &dev->iamthif_cl) {
- rets = amthi_read(dev, file, ubuf, length, offset);
+ rets = mei_amthif_read(dev, file, ubuf, length, offset);
goto out;
}
- if (cl->read_cb && cl->read_cb->information > *offset) {
+ if (cl->read_cb && cl->read_cb->buf_idx > *offset) {
cb = cl->read_cb;
goto copy_buffer;
- } else if (cl->read_cb && cl->read_cb->information > 0 &&
- cl->read_cb->information <= *offset) {
+ } else if (cl->read_cb && cl->read_cb->buf_idx > 0 &&
+ cl->read_cb->buf_idx <= *offset) {
cb = cl->read_cb;
rets = 0;
goto free;
- } else if ((!cl->read_cb || !cl->read_cb->information) &&
- *offset > 0) {
+ } else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) {
/*Offset needs to be cleaned for contiguous reads*/
*offset = 0;
rets = 0;
@@ -481,16 +372,15 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
copy_buffer:
dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
cb->response_buffer.size);
- dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
- cb->information);
- if (length == 0 || ubuf == NULL || *offset > cb->information) {
+ dev_dbg(&dev->pdev->dev, "cb->buf_idx - %lu\n", cb->buf_idx);
+ if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
rets = -EMSGSIZE;
goto free;
}
- /* length is being truncated to PAGE_SIZE, however, */
- /* information size may be longer */
- length = min_t(size_t, length, (cb->information - *offset));
+ /* length is being truncated to PAGE_SIZE,
+ * however buf_idx may point beyond that */
+ length = min_t(size_t, length, cb->buf_idx - *offset);
if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
rets = -EFAULT;
@@ -499,15 +389,15 @@ copy_buffer:
rets = length;
*offset += length;
- if ((unsigned long)*offset < cb->information)
+ if ((unsigned long)*offset < cb->buf_idx)
goto out;
free:
cb_pos = find_read_list_entry(dev, cl);
/* Remove entry from read list */
if (cb_pos)
- list_del(&cb_pos->cb_list);
- mei_free_cb_private(cb);
+ list_del(&cb_pos->list);
+ mei_io_cb_free(cb);
cl->reading_state = MEI_IDLE;
cl->read_cb = NULL;
cl->read_pending = 0;
@@ -516,7 +406,6 @@ out:
mutex_unlock(&dev->device_lock);
return rets;
}
-
/**
* mei_write - the write function.
*
@@ -546,23 +435,39 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
mutex_lock(&dev->device_lock);
if (dev->dev_state != MEI_DEV_ENABLED) {
- mutex_unlock(&dev->device_lock);
- return -ENODEV;
+ rets = -ENODEV;
+ goto err;
}
+ i = mei_me_cl_by_id(dev, cl->me_client_id);
+ if (i < 0) {
+ rets = -ENODEV;
+ goto err;
+ }
+ if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
+ rets = -EMSGSIZE;
+ goto err;
+ }
+
+ if (cl->state != MEI_FILE_CONNECTED) {
+ rets = -ENODEV;
+ dev_err(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
+ cl->host_client_id, cl->me_client_id);
+ goto err;
+ }
if (cl == &dev->iamthif_cl) {
- write_cb = find_amthi_read_list_entry(dev, file);
+ write_cb = mei_amthif_find_read_list_entry(dev, file);
if (write_cb) {
timeout = write_cb->read_time +
- msecs_to_jiffies(IAMTHIF_READ_TIMER);
+ mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
if (time_after(jiffies, timeout) ||
- cl->reading_state == MEI_READ_COMPLETE) {
- *offset = 0;
- list_del(&write_cb->cb_list);
- mei_free_cb_private(write_cb);
- write_cb = NULL;
+ cl->reading_state == MEI_READ_COMPLETE) {
+ *offset = 0;
+ list_del(&write_cb->list);
+ mei_io_cb_free(write_cb);
+ write_cb = NULL;
}
}
}
@@ -572,8 +477,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
*offset = 0;
write_cb = find_read_list_entry(dev, cl);
if (write_cb) {
- list_del(&write_cb->cb_list);
- mei_free_cb_private(write_cb);
+ list_del(&write_cb->list);
+ mei_io_cb_free(write_cb);
write_cb = NULL;
cl->reading_state = MEI_IDLE;
cl->read_cb = NULL;
@@ -583,24 +488,21 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
*offset = 0;
- write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+ write_cb = mei_io_cb_init(cl, file);
if (!write_cb) {
- mutex_unlock(&dev->device_lock);
- return -ENOMEM;
+ dev_err(&dev->pdev->dev, "write cb allocation failed\n");
+ rets = -ENOMEM;
+ goto err;
}
+ rets = mei_io_cb_alloc_req_buf(write_cb, length);
+ if (rets)
+ goto err;
- write_cb->file_object = file;
- write_cb->file_private = cl;
- write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
- rets = -ENOMEM;
- if (!write_cb->request_buffer.data)
- goto unlock_dev;
-
- dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
+ dev_dbg(&dev->pdev->dev, "cb request size = %zd\n", length);
- rets = -EFAULT;
- if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
- goto unlock_dev;
+ rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
+ if (rets)
+ goto err;
cl->sm_state = 0;
if (length == 4 &&
@@ -612,139 +514,71 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
write_cb->request_buffer.data, 4) == 0)))
cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
- INIT_LIST_HEAD(&write_cb->cb_list);
if (cl == &dev->iamthif_cl) {
- write_cb->response_buffer.data =
- kmalloc(dev->iamthif_mtu, GFP_KERNEL);
- if (!write_cb->response_buffer.data) {
- rets = -ENOMEM;
- goto unlock_dev;
- }
- if (dev->dev_state != MEI_DEV_ENABLED) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
- if (i < 0) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- if (length > dev->me_clients[i].props.max_msg_length ||
- length <= 0) {
- rets = -EMSGSIZE;
- goto unlock_dev;
- }
+ rets = mei_amthif_write(dev, write_cb);
- write_cb->response_buffer.size = dev->iamthif_mtu;
- write_cb->major_file_operations = MEI_IOCTL;
- write_cb->information = 0;
- write_cb->request_buffer.size = length;
- if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
- rets = -ENODEV;
- goto unlock_dev;
- }
-
- if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
- dev->iamthif_state != MEI_IAMTHIF_IDLE) {
- dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
- (int) dev->iamthif_state);
- dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
- list_add_tail(&write_cb->cb_list,
- &dev->amthi_cmd_list.mei_cb.cb_list);
- rets = length;
- } else {
- dev_dbg(&dev->pdev->dev, "call amthi write\n");
- rets = amthi_write(dev, write_cb);
-
- if (rets) {
- dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
- rets);
- goto unlock_dev;
- }
- rets = length;
+ if (rets) {
+ dev_err(&dev->pdev->dev,
+ "amthi write failed with status = %d\n", rets);
+ goto err;
}
mutex_unlock(&dev->device_lock);
- return rets;
+ return length;
}
- write_cb->major_file_operations = MEI_WRITE;
- /* make sure information is zero before we start */
-
- write_cb->information = 0;
- write_cb->request_buffer.size = length;
+ write_cb->fop_type = MEI_FOP_WRITE;
dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id);
- if (cl->state != MEI_FILE_CONNECTED) {
- rets = -ENODEV;
- dev_dbg(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
- cl->host_client_id,
- cl->me_client_id);
- goto unlock_dev;
- }
- i = mei_me_cl_by_id(dev, cl->me_client_id);
- if (i < 0) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
- rets = -EINVAL;
- goto unlock_dev;
- }
- write_cb->file_private = cl;
-
rets = mei_flow_ctrl_creds(dev, cl);
if (rets < 0)
- goto unlock_dev;
+ goto err;
- if (rets && dev->mei_host_buffer_is_empty) {
- rets = 0;
- dev->mei_host_buffer_is_empty = false;
- if (length > mei_hbuf_max_data(dev)) {
- mei_hdr.length = mei_hbuf_max_data(dev);
- mei_hdr.msg_complete = 0;
- } else {
- mei_hdr.length = length;
- mei_hdr.msg_complete = 1;
- }
- mei_hdr.host_addr = cl->host_client_id;
- mei_hdr.me_addr = cl->me_client_id;
- mei_hdr.reserved = 0;
- dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
- *((u32 *) &mei_hdr));
- if (mei_write_message(dev, &mei_hdr,
- (unsigned char *) (write_cb->request_buffer.data),
- mei_hdr.length)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
+ if (rets == 0 || dev->mei_host_buffer_is_empty == false) {
+ write_cb->buf_idx = 0;
+ mei_hdr.msg_complete = 0;
cl->writing_state = MEI_WRITING;
- write_cb->information = mei_hdr.length;
- if (mei_hdr.msg_complete) {
- if (mei_flow_ctrl_reduce(dev, cl)) {
- rets = -ENODEV;
- goto unlock_dev;
- }
- list_add_tail(&write_cb->cb_list,
- &dev->write_waiting_list.mei_cb.cb_list);
- } else {
- list_add_tail(&write_cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
- }
+ goto out;
+ }
+ dev->mei_host_buffer_is_empty = false;
+ if (length > mei_hbuf_max_data(dev)) {
+ mei_hdr.length = mei_hbuf_max_data(dev);
+ mei_hdr.msg_complete = 0;
} else {
+ mei_hdr.length = length;
+ mei_hdr.msg_complete = 1;
+ }
+ mei_hdr.host_addr = cl->host_client_id;
+ mei_hdr.me_addr = cl->me_client_id;
+ mei_hdr.reserved = 0;
+ dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
+ *((u32 *) &mei_hdr));
+ if (mei_write_message(dev, &mei_hdr,
+ write_cb->request_buffer.data, mei_hdr.length)) {
+ rets = -ENODEV;
+ goto err;
+ }
+ cl->writing_state = MEI_WRITING;
+ write_cb->buf_idx = mei_hdr.length;
- write_cb->information = 0;
- cl->writing_state = MEI_WRITING;
- list_add_tail(&write_cb->cb_list,
- &dev->write_list.mei_cb.cb_list);
+out:
+ if (mei_hdr.msg_complete) {
+ if (mei_flow_ctrl_reduce(dev, cl)) {
+ rets = -ENODEV;
+ goto err;
+ }
+ list_add_tail(&write_cb->list, &dev->write_waiting_list.list);
+ } else {
+ list_add_tail(&write_cb->list, &dev->write_list.list);
}
+
mutex_unlock(&dev->device_lock);
return length;
-unlock_dev:
+err:
mutex_unlock(&dev->device_lock);
- mei_free_cb_private(write_cb);
+ mei_io_cb_free(write_cb);
return rets;
}
@@ -860,15 +694,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
if (cl == &dev->iamthif_cl) {
- mutex_unlock(&dev->device_lock);
- poll_wait(file, &dev->iamthif_cl.wait, wait);
- mutex_lock(&dev->device_lock);
- if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
- dev->iamthif_file_object == file) {
- mask |= (POLLIN | POLLRDNORM);
- dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
- mei_run_next_iamthif_cmd(dev);
- }
+ mask = mei_amthif_poll(dev, file, wait);
goto out;
}
@@ -917,7 +743,7 @@ static struct miscdevice mei_misc_device = {
*
* returns true if ME Interface is valid, false otherwise
*/
-static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
+static bool mei_quirk_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
u32 reg;
@@ -939,7 +765,7 @@ static bool __devinit mei_quirk_probe(struct pci_dev *pdev,
*
* returns 0 on success, <0 on failure.
*/
-static int __devinit mei_probe(struct pci_dev *pdev,
+static int mei_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct mei_device *dev;
@@ -1003,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
goto disable_msi;
}
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+ INIT_WORK(&dev->init_work, mei_host_client_init);
+
if (mei_hw_init(dev)) {
dev_err(&pdev->dev, "init hw failure.\n");
err = -ENODEV;
@@ -1054,7 +882,7 @@ end:
* mei_remove is called by the PCI subsystem to alert the driver
* that it should release a PCI device.
*/
-static void __devexit mei_remove(struct pci_dev *pdev)
+static void mei_remove(struct pci_dev *pdev)
{
struct mei_device *dev;
@@ -1087,8 +915,8 @@ static void __devexit mei_remove(struct pci_dev *pdev)
/* remove entry if already in list */
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
- mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
- mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
+ mei_me_cl_unlink(dev, &dev->wd_cl);
+ mei_me_cl_unlink(dev, &dev->iamthif_cl);
dev->iamthif_current_cb = NULL;
dev->me_clients_num = 0;
@@ -1195,8 +1023,8 @@ static struct pci_driver mei_driver = {
.name = KBUILD_MODNAME,
.id_table = mei_pci_tbl,
.probe = mei_probe,
- .remove = __devexit_p(mei_remove),
- .shutdown = __devexit_p(mei_remove),
+ .remove = mei_remove,
+ .shutdown = mei_remove,
.driver.pm = MEI_PM_OPS,
};
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index adb35fb9281c..25da04549d04 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/watchdog.h>
+#include <linux/poll.h>
#include <linux/mei.h>
#include "hw.h"
@@ -125,13 +126,20 @@ enum mei_wd_states {
MEI_WD_STOPPING,
};
-/* MEI CB */
-enum mei_cb_major_types {
- MEI_READ = 0,
- MEI_WRITE,
- MEI_IOCTL,
- MEI_OPEN,
- MEI_CLOSE
+/**
+ * enum mei_cb_file_ops - file operation associated with the callback
+ * @MEI_FOP_READ - read
+ * @MEI_FOP_WRITE - write
+ * @MEI_FOP_IOCTL - ioctl
+ * @MEI_FOP_OPEN - open
+ * @MEI_FOP_CLOSE - close
+ */
+enum mei_cb_file_ops {
+ MEI_FOP_READ = 0,
+ MEI_FOP_WRITE,
+ MEI_FOP_IOCTL,
+ MEI_FOP_OPEN,
+ MEI_FOP_CLOSE
};
/*
@@ -143,13 +151,21 @@ struct mei_message_data {
};
+struct mei_cl;
+
+/**
+ * struct mei_cl_cb - file operation callback structure
+ *
+ * @cl - file client who is running this operation
+ * @fop_type - file operation type
+ */
struct mei_cl_cb {
- struct list_head cb_list;
- enum mei_cb_major_types major_file_operations;
- void *file_private;
+ struct list_head list;
+ struct mei_cl *cl;
+ enum mei_cb_file_ops fop_type;
struct mei_message_data request_buffer;
struct mei_message_data response_buffer;
- unsigned long information;
+ unsigned long buf_idx;
unsigned long read_time;
struct file *file_object;
};
@@ -175,29 +191,23 @@ struct mei_cl {
struct mei_cl_cb *read_cb;
};
-struct mei_io_list {
- struct mei_cl_cb mei_cb;
-};
-
/**
- * struct mei_deive - MEI private device struct
+ * struct mei_device - MEI private device struct
* @hbuf_depth - depth of host(write) buffer
+ * @wr_ext_msg - buffer for hbm control responses (set in read cycle)
*/
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
/*
* lists of queues
*/
- /* array of pointers to aio lists */
- struct mei_io_list read_list; /* driver read queue */
- struct mei_io_list write_list; /* driver write queue */
- struct mei_io_list write_waiting_list; /* write waiting queue */
- struct mei_io_list ctrl_wr_list; /* managed write IOCTL list */
- struct mei_io_list ctrl_rd_list; /* managed read IOCTL list */
- struct mei_io_list amthi_cmd_list; /* amthi list for cmd waiting */
-
- /* driver managed amthi list for reading completed amthi cmd data */
- struct mei_io_list amthi_read_complete_list;
+ /* array of pointers to aio lists */
+ struct mei_cl_cb read_list; /* driver read queue */
+ struct mei_cl_cb write_list; /* driver write queue */
+ struct mei_cl_cb write_waiting_list; /* write waiting queue */
+ struct mei_cl_cb ctrl_wr_list; /* managed write IOCTL list */
+ struct mei_cl_cb ctrl_rd_list; /* managed read IOCTL list */
+
/*
* list of files
*/
@@ -235,11 +245,13 @@ struct mei_device {
u16 init_clients_timer;
bool need_reset;
- u32 extra_write_index;
unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */
- u32 wr_msg_buf[128]; /* used for control messages */
- u32 ext_msg_buf[8]; /* for control responses */
u32 rd_msg_hdr;
+ u32 wr_msg_buf[128]; /* used for control messages */
+ struct {
+ struct mei_msg_hdr hdr;
+ unsigned char data[4]; /* All HBM messages are 4 bytes */
+ } wr_ext_msg; /* for control responses */
struct hbm_version version;
@@ -253,12 +265,15 @@ struct mei_device {
struct mei_cl wd_cl;
enum mei_wd_states wd_state;
- bool wd_interface_reg;
bool wd_pending;
u16 wd_timeout;
unsigned char wd_data[MEI_WD_START_MSG_SIZE];
+ /* amthif list for cmd waiting */
+ struct mei_cl_cb amthif_cmd_list;
+ /* driver managed amthif list for reading completed amthif cmd data */
+ struct mei_cl_cb amthif_rd_complete_list;
struct file *iamthif_file_object;
struct mei_cl iamthif_cl;
struct mei_cl_cb *iamthif_current_cb;
@@ -272,8 +287,15 @@ struct mei_device {
bool iamthif_flow_control_pending;
bool iamthif_ioctl;
bool iamthif_canceled;
+
+ struct work_struct init_work;
};
+static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
+{
+ return msecs_to_jiffies(sec * MSEC_PER_SEC);
+}
+
/*
* mei init function prototypes
@@ -284,21 +306,34 @@ int mei_hw_init(struct mei_device *dev);
int mei_task_initialize_clients(void *data);
int mei_initialize_clients(struct mei_device *dev);
int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
-void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
-void mei_host_init_iamthif(struct mei_device *dev);
void mei_allocate_me_clients_storage(struct mei_device *dev);
-int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
+int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
const uuid_le *cguid, u8 host_client_id);
+void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl);
int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
/*
- * MEI IO List Functions
+ * MEI IO Functions
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
+void mei_io_cb_free(struct mei_cl_cb *priv_cb);
+int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
+int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
+
+
+/**
+ * mei_io_list_init - Sets up a queue list.
+ *
+ * @list: An instance cl callback structure
*/
-void mei_io_list_init(struct mei_io_list *list);
-void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
+static inline void mei_io_list_init(struct mei_cl_cb *list)
+{
+ INIT_LIST_HEAD(&list->list);
+}
+void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl);
/*
* MEI ME Client Functions
@@ -330,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
*/
void mei_host_start_message(struct mei_device *dev);
void mei_host_enum_clients_message(struct mei_device *dev);
-int mei_host_client_properties(struct mei_device *dev);
+int mei_host_client_enumerate(struct mei_device *dev);
+void mei_host_client_init(struct work_struct *work);
/*
* MEI interrupt functions prototype
@@ -347,18 +383,40 @@ int mei_ioctl_connect_client(struct file *file,
int mei_start_read(struct mei_device *dev, struct mei_cl *cl);
-int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
-int amthi_read(struct mei_device *dev, struct file *file,
- char __user *ubuf, size_t length, loff_t *offset);
+/*
+ * AMTHIF - AMT Host Interface Functions
+ */
+void mei_amthif_reset_params(struct mei_device *dev);
+
+void mei_amthif_host_init(struct mei_device *dev);
+
+int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
-struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
+int mei_amthif_read(struct mei_device *dev, struct file *file,
+ char __user *ubuf, size_t length, loff_t *offset);
+
+unsigned int mei_amthif_poll(struct mei_device *dev,
+ struct file *file, poll_table *wait);
+
+int mei_amthif_release(struct mei_device *dev, struct file *file);
+
+struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
struct file *file);
-void mei_run_next_iamthif_cmd(struct mei_device *dev);
+void mei_amthif_run_next_cmd(struct mei_device *dev);
+
-void mei_free_cb_private(struct mei_cl_cb *priv_cb);
+int mei_amthif_read_message(struct mei_cl_cb *complete_list,
+ struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
+int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
+ struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);
+
+void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
+int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
+ struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
+int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
/*
* Register Access Function
@@ -437,4 +495,15 @@ void mei_csr_clear_his(struct mei_device *dev);
void mei_enable_interrupts(struct mei_device *dev);
void mei_disable_interrupts(struct mei_device *dev);
+static inline struct mei_msg_hdr *mei_hbm_hdr(u32 *buf, size_t length)
+{
+ struct mei_msg_hdr *hdr = (struct mei_msg_hdr *)buf;
+ hdr->host_addr = 0;
+ hdr->me_addr = 0;
+ hdr->length = length;
+ hdr->msg_complete = 1;
+ hdr->reserved = 0;
+ return hdr;
+}
+
#endif
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index d96c537f046f..636409f9667f 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -62,6 +62,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
*/
int mei_wd_host_init(struct mei_device *dev)
{
+ int id;
mei_cl_init(&dev->wd_cl, dev);
/* look for WD client and connect to it */
@@ -69,12 +70,11 @@ int mei_wd_host_init(struct mei_device *dev)
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
dev->wd_state = MEI_WD_IDLE;
- /* find ME WD client */
- mei_me_cl_update_filext(dev, &dev->wd_cl,
+ /* Connect WD ME client to the host client */
+ id = mei_me_cl_link(dev, &dev->wd_cl,
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
- dev_dbg(&dev->pdev->dev, "wd: check client\n");
- if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
+ if (id < 0) {
dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
return -ENOENT;
}
@@ -85,7 +85,7 @@ int mei_wd_host_init(struct mei_device *dev)
dev->wd_cl.host_client_id = 0;
return -EIO;
}
- dev->wd_cl.timer_count = CONNECT_TIMEOUT;
+ dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT;
return 0;
}
@@ -360,23 +360,20 @@ void mei_watchdog_register(struct mei_device *dev)
if (watchdog_register_device(&amt_wd_dev)) {
dev_err(&dev->pdev->dev,
"wd: unable to register watchdog device.\n");
- dev->wd_interface_reg = false;
return;
}
dev_dbg(&dev->pdev->dev,
"wd: successfully register watchdog interface.\n");
- dev->wd_interface_reg = true;
watchdog_set_drvdata(&amt_wd_dev, dev);
}
void mei_watchdog_unregister(struct mei_device *dev)
{
- if (!dev->wd_interface_reg)
+ if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status))
return;
watchdog_set_drvdata(&amt_wd_dev, NULL);
watchdog_unregister_device(&amt_wd_dev);
- dev->wd_interface_reg = false;
}
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index c9f20dae1855..931e635aa491 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -666,7 +666,7 @@ static struct bin_attribute pch_bin_attr = {
.write = pch_phub_bin_write,
};
-static int __devinit pch_phub_probe(struct pci_dev *pdev,
+static int pch_phub_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int retval;
@@ -819,7 +819,7 @@ err_pci_enable_dev:
return ret;
}
-static void __devexit pch_phub_remove(struct pci_dev *pdev)
+static void pch_phub_remove(struct pci_dev *pdev)
{
struct pch_phub_reg *chip = pci_get_drvdata(pdev);
@@ -888,7 +888,7 @@ static struct pci_driver pch_phub_driver = {
.name = "pch_phub",
.id_table = pch_phub_pcidev_id,
.probe = pch_phub_probe,
- .remove = __devexit_p(pch_phub_remove),
+ .remove = pch_phub_remove,
.suspend = pch_phub_suspend,
.resume = pch_phub_resume
};
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 21b28fc6d912..68b7c773d2cf 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -324,7 +324,7 @@ static irqreturn_t phantom_isr(int irq, void *data)
* Init and deinit driver
*/
-static unsigned int __devinit phantom_get_free(void)
+static unsigned int phantom_get_free(void)
{
unsigned int i;
@@ -335,7 +335,7 @@ static unsigned int __devinit phantom_get_free(void)
return i;
}
-static int __devinit phantom_probe(struct pci_dev *pdev,
+static int phantom_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id)
{
struct phantom_device *pht;
@@ -435,7 +435,7 @@ err:
return retval;
}
-static void __devexit phantom_remove(struct pci_dev *pdev)
+static void phantom_remove(struct pci_dev *pdev)
{
struct phantom_device *pht = pci_get_drvdata(pdev);
unsigned int minor = MINOR(pht->cdev.dev);
@@ -487,7 +487,7 @@ static int phantom_resume(struct pci_dev *pdev)
#define phantom_resume NULL
#endif
-static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
+static struct pci_device_id phantom_pci_tbl[] = {
{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
.subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
.class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
@@ -499,7 +499,7 @@ static struct pci_driver phantom_pci_driver = {
.name = "phantom",
.id_table = phantom_pci_tbl,
.probe = phantom_probe,
- .remove = __devexit_p(phantom_remove),
+ .remove = phantom_remove,
.suspend = phantom_suspend,
.resume = phantom_resume
};
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index 4999b34b7a60..7003031c9181 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -76,7 +76,7 @@ struct pti_dev {
*/
static DEFINE_MUTEX(alloclock);
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x82B)},
{0}
};
@@ -796,7 +796,7 @@ static const struct tty_port_operations tty_port_ops = {
* 0 for success
* otherwise, error
*/
-static int __devinit pti_pci_probe(struct pci_dev *pdev,
+static int pti_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
unsigned int a;
@@ -879,7 +879,7 @@ err:
* PCI bus.
* @pdev: variable containing pci info of PTI.
*/
-static void __devexit pti_pci_remove(struct pci_dev *pdev)
+static void pti_pci_remove(struct pci_dev *pdev)
{
struct pti_dev *drv_data = pci_get_drvdata(pdev);
@@ -901,7 +901,7 @@ static struct pci_driver pti_pci_driver = {
.name = PCINAME,
.id_table = pci_ids,
.probe = pti_pci_probe,
- .remove = __devexit_p(pti_pci_remove),
+ .remove = pti_pci_remove,
};
/**
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
index 123ed98eec3e..7deb25dc86a7 100644
--- a/drivers/misc/spear13xx_pcie_gadget.c
+++ b/drivers/misc/spear13xx_pcie_gadget.c
@@ -711,7 +711,7 @@ static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
}
-static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
+static int spear_pcie_gadget_probe(struct platform_device *pdev)
{
struct resource *res0, *res1;
unsigned int status = 0;
@@ -853,7 +853,7 @@ err_rel_res0:
return status;
}
-static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
+static int spear_pcie_gadget_remove(struct platform_device *pdev)
{
struct resource *res0, *res1;
static struct pcie_gadget_target *target;
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index 46937b107261..b90a2241d79c 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -511,7 +511,6 @@ long st_register(struct st_proto_s *new_proto)
unsigned long flags = 0;
st_kim_ref(&st_gdata, 0);
- pr_info("%s(%d) ", __func__, new_proto->chnl_id);
if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
|| new_proto->reg_complete_cb == NULL) {
pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 04a819944f6b..9ff942a346ed 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -705,9 +705,9 @@ static const struct file_operations list_debugfs_fops = {
static struct dentry *kim_debugfs_dir;
static int kim_probe(struct platform_device *pdev)
{
- long status;
struct kim_data_s *kim_gdata;
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
+ int err;
if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
/* multiple devices could exist */
@@ -724,10 +724,11 @@ static int kim_probe(struct platform_device *pdev)
}
dev_set_drvdata(&pdev->dev, kim_gdata);
- status = st_core_init(&kim_gdata->core_data);
- if (status != 0) {
+ err = st_core_init(&kim_gdata->core_data);
+ if (err != 0) {
pr_err(" ST core init failed");
- return -EIO;
+ err = -EIO;
+ goto err_core_init;
}
/* refer to itself */
kim_gdata->core_data->kim_data = kim_gdata;
@@ -738,10 +739,10 @@ static int kim_probe(struct platform_device *pdev)
init_completion(&kim_gdata->kim_rcvd);
init_completion(&kim_gdata->ldisc_installed);
- status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
- if (status) {
+ err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
+ if (err) {
pr_err("failed to create sysfs entries");
- return status;
+ goto err_sysfs_group;
}
/* copying platform data */
@@ -753,8 +754,8 @@ static int kim_probe(struct platform_device *pdev)
kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
if (IS_ERR(kim_debugfs_dir)) {
pr_err(" debugfs entries creation failed ");
- kim_debugfs_dir = NULL;
- return -EIO;
+ err = -EIO;
+ goto err_debugfs_dir;
}
debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
@@ -763,6 +764,17 @@ static int kim_probe(struct platform_device *pdev)
kim_gdata, &list_debugfs_fops);
pr_info(" debugfs entries created ");
return 0;
+
+err_debugfs_dir:
+ sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
+
+err_sysfs_group:
+ st_core_exit(kim_gdata->core_data);
+
+err_core_init:
+ kfree(kim_gdata);
+
+ return err;
}
static int kim_remove(struct platform_device *pdev)
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index 5acbba120de0..1d86407189eb 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -54,7 +54,7 @@ static const struct attribute_group dac7512_attr_group = {
.attrs = dac7512_attributes,
};
-static int __devinit dac7512_probe(struct spi_device *spi)
+static int dac7512_probe(struct spi_device *spi)
{
int ret;
@@ -67,7 +67,7 @@ static int __devinit dac7512_probe(struct spi_device *spi)
return sysfs_create_group(&spi->dev.kobj, &dac7512_attr_group);
}
-static int __devexit dac7512_remove(struct spi_device *spi)
+static int dac7512_remove(struct spi_device *spi)
{
sysfs_remove_group(&spi->dev.kobj, &dac7512_attr_group);
return 0;
@@ -79,7 +79,7 @@ static struct spi_driver dac7512_driver = {
.owner = THIS_MODULE,
},
.probe = dac7512_probe,
- .remove = __devexit_p(dac7512_remove),
+ .remove = dac7512_remove,
};
module_spi_driver(dac7512_driver);
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 0beb298a17dd..1e7bc0eb081e 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -347,7 +347,7 @@ static int tsl2550_init_client(struct i2c_client *client)
*/
static struct i2c_driver tsl2550_driver;
-static int __devinit tsl2550_probe(struct i2c_client *client,
+static int tsl2550_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -405,7 +405,7 @@ exit:
return err;
}
-static int __devexit tsl2550_remove(struct i2c_client *client)
+static int tsl2550_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
@@ -450,7 +450,7 @@ static struct i2c_driver tsl2550_driver = {
.suspend = tsl2550_suspend,
.resume = tsl2550_resume,
.probe = tsl2550_probe,
- .remove = __devexit_p(tsl2550_remove),
+ .remove = tsl2550_remove,
.id_table = tsl2550_id,
};
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 172a768036d8..21056b9ef0a0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -57,6 +57,7 @@ MODULE_ALIAS("mmc:block");
#define INAND_CMD38_ARG_SECERASE 0x80
#define INAND_CMD38_ARG_SECTRIM1 0x81
#define INAND_CMD38_ARG_SECTRIM2 0x88
+#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
static DEFINE_MUTEX(block_mutex);
@@ -126,6 +127,10 @@ enum mmc_blk_status {
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+ struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
struct mmc_blk_data *md;
@@ -357,6 +362,38 @@ out:
return ERR_PTR(err);
}
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+ u32 retries_max)
+{
+ int err;
+ u32 retry_count = 0;
+
+ if (!status || !retries_max)
+ return -EINVAL;
+
+ do {
+ err = get_card_status(card, status, 5);
+ if (err)
+ break;
+
+ if (!R1_STATUS(*status) &&
+ (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+ break; /* RPMB programming operation complete */
+
+ /*
+ * Rechedule to give the MMC device a chance to continue
+ * processing the previous command without being polled too
+ * frequently.
+ */
+ usleep_range(1000, 5000);
+ } while (++retry_count < retries_max);
+
+ if (retry_count == retries_max)
+ err = -EPERM;
+
+ return err;
+}
+
static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_ioc_cmd __user *ic_ptr)
{
@@ -368,6 +405,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_request mrq = {NULL};
struct scatterlist sg;
int err;
+ int is_rpmb = false;
+ u32 status = 0;
/*
* The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -387,6 +426,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_err;
}
+ if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+ is_rpmb = true;
+
card = md->queue.card;
if (IS_ERR(card)) {
err = PTR_ERR(card);
@@ -437,12 +479,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
mmc_claim_host(card->host);
+ err = mmc_blk_part_switch(card, md);
+ if (err)
+ goto cmd_rel_host;
+
if (idata->ic.is_acmd) {
err = mmc_app_cmd(card->host, card);
if (err)
goto cmd_rel_host;
}
+ if (is_rpmb) {
+ err = mmc_set_blockcount(card, data.blocks,
+ idata->ic.write_flag & (1 << 31));
+ if (err)
+ goto cmd_rel_host;
+ }
+
mmc_wait_for_req(card->host, &mrq);
if (cmd.error) {
@@ -478,6 +531,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
}
}
+ if (is_rpmb) {
+ /*
+ * Ensure RPMB command has completed by polling CMD13
+ * "Send Status".
+ */
+ err = ioctl_rpmb_card_status_poll(card, &status, 5);
+ if (err)
+ dev_err(mmc_dev(card->host),
+ "%s: Card Status=0x%08X, error %d\n",
+ __func__, status, err);
+ }
+
cmd_rel_host:
mmc_release_host(card->host);
@@ -1034,6 +1099,9 @@ static int mmc_blk_err_check(struct mmc_card *card,
*/
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
u32 status;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
do {
int err = get_card_status(card, &status, 5);
if (err) {
@@ -1041,6 +1109,17 @@ static int mmc_blk_err_check(struct mmc_card *card,
req->rq_disk->disk_name, err);
return MMC_BLK_CMD_ERR;
}
+
+ /* Timeout if the device never becomes ready for data
+ * and never leaves the program state.
+ */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state!"\
+ " %s %s\n", mmc_hostname(card->host),
+ req->rq_disk->disk_name, __func__);
+
+ return MMC_BLK_CMD_ERR;
+ }
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
@@ -1504,6 +1583,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
md->disk->queue = md->queue.queue;
md->disk->driverfs_dev = parent;
set_disk_ro(md->disk, md->read_only || default_ro);
+ if (area_type & MMC_BLK_DATA_AREA_RPMB)
+ md->disk->flags |= GENHD_FL_NO_PART_SCAN;
/*
* As discussed on lkml, GENHD_FL_REMOVABLE should:
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index e360a979857d..fadf52eb5d70 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -68,6 +68,16 @@ static int mmc_queue_thread(void *d)
if (req || mq->mqrq_prev->req) {
set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req);
+
+ /*
+ * Current request becomes previous request
+ * and vice versa.
+ */
+ mq->mqrq_prev->brq.mrq.data = NULL;
+ mq->mqrq_prev->req = NULL;
+ tmp = mq->mqrq_prev;
+ mq->mqrq_prev = mq->mqrq_cur;
+ mq->mqrq_cur = tmp;
} else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
@@ -77,13 +87,6 @@ static int mmc_queue_thread(void *d)
schedule();
down(&mq->thread_sem);
}
-
- /* Current request becomes previous request and vice versa. */
- mq->mqrq_prev->brq.mrq.data = NULL;
- mq->mqrq_prev->req = NULL;
- tmp = mq->mqrq_prev;
- mq->mqrq_prev = mq->mqrq_cur;
- mq->mqrq_cur = tmp;
} while (1);
up(&mq->thread_sem);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 9b68933f27e7..420cb6753c1e 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -225,8 +225,7 @@ static void mmc_release_card(struct device *dev)
sdio_free_common_cis(card);
- if (card->info)
- kfree(card->info);
+ kfree(card->info);
kfree(card);
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 06c42cfb7c34..aaed7687cf09 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -42,6 +42,9 @@
#include "sd_ops.h"
#include "sdio_ops.h"
+/* If the device is not responding */
+#define MMC_CORE_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+
/*
* Background operations can take a long time, depending on the housekeeping
* operations the card has to perform.
@@ -1631,6 +1634,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
{
struct mmc_command cmd = {0};
unsigned int qty = 0;
+ unsigned long timeout;
int err;
/*
@@ -1708,6 +1712,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
if (mmc_host_is_spi(card->host))
goto out;
+ timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
do {
memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = MMC_SEND_STATUS;
@@ -1721,8 +1726,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
err = -EIO;
goto out;
}
+
+ /* Timeout if the device never becomes ready for data and
+ * never leaves the program state.
+ */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s\n",
+ mmc_hostname(card->host), __func__);
+ err = -EIO;
+ goto out;
+ }
+
} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
- R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
+ (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
out:
return err;
}
@@ -1942,6 +1958,20 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
}
EXPORT_SYMBOL(mmc_set_blocklen);
+int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+ bool is_rel_write)
+{
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_SET_BLOCK_COUNT;
+ cmd.arg = blockcount & 0x0000FFFF;
+ if (is_rel_write)
+ cmd.arg |= 1 << 31;
+ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blockcount);
+
static void mmc_hw_reset_for_init(struct mmc_host *host)
{
if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index d96c643dde1c..35c2f85b1956 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -144,6 +144,22 @@ static int mmc_ios_show(struct seq_file *s, void *data)
}
seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ str = "3.30 V";
+ break;
+ case MMC_SIGNAL_VOLTAGE_180:
+ str = "1.80 V";
+ break;
+ case MMC_SIGNAL_VOLTAGE_120:
+ str = "1.20 V";
+ break;
+ default:
+ str = "invalid";
+ break;
+ }
+ seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
+
return 0;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 7cc46382fd64..e6e39111e05b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -239,7 +239,7 @@ static void mmc_select_card_type(struct mmc_card *card)
{
struct mmc_host *host = card->host;
u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
- unsigned int caps = host->caps, caps2 = host->caps2;
+ u32 caps = host->caps, caps2 = host->caps2;
unsigned int hs_max_dtr = 0;
if (card_type & EXT_CSD_CARD_TYPE_26)
@@ -491,6 +491,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+
+ /*
+ * RPMB regions are defined in multiples of 128K.
+ */
+ card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
+ if (ext_csd[EXT_CSD_RPMB_MULT]) {
+ mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
+ EXT_CSD_PART_CONFIG_ACC_RPMB,
+ "rpmb", 0, false,
+ MMC_BLK_DATA_AREA_RPMB);
+ }
}
card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
@@ -615,6 +626,8 @@ MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
card->ext_csd.enhanced_area_offset);
MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
+MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
+MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
static struct attribute *mmc_std_attrs[] = {
&dev_attr_cid.attr,
@@ -630,6 +643,8 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_serial.attr,
&dev_attr_enhanced_area_offset.attr,
&dev_attr_enhanced_area_size.attr,
+ &dev_attr_raw_rpmb_size_mult.attr,
+ &dev_attr_rel_sectors.attr,
NULL,
};
@@ -1051,6 +1066,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
if (max_dtr > card->ext_csd.hs_max_dtr)
max_dtr = card->ext_csd.hs_max_dtr;
+ if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+ max_dtr = 52000000;
} else if (max_dtr > card->csd.max_dtr) {
max_dtr = card->csd.max_dtr;
}
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index a0e172042e65..6d8f7012d73a 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -21,6 +21,8 @@
#include "core.h"
#include "mmc_ops.h"
+#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
@@ -409,6 +411,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
{
int err;
struct mmc_command cmd = {0};
+ unsigned long timeout;
u32 status;
BUG_ON(!card);
@@ -437,6 +440,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
return 0;
/* Must check status to be sure of no errors */
+ timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
do {
err = mmc_send_status(card, &status);
if (err)
@@ -445,6 +449,13 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
break;
if (mmc_host_is_spi(card->host))
break;
+
+ /* Timeout if the device never leaves the program state. */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s\n",
+ mmc_hostname(card->host), __func__);
+ return -ETIMEDOUT;
+ }
} while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
if (mmc_host_is_spi(card->host)) {
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 6bf68799fe97..5e57048e2c1d 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -193,7 +193,21 @@ static int sdio_bus_remove(struct device *dev)
}
#ifdef CONFIG_PM
+
+#ifdef CONFIG_PM_SLEEP
+static int pm_no_operation(struct device *dev)
+{
+ /*
+ * Prevent the PM core from calling SDIO device drivers' suspend
+ * callback routines, which it is not supposed to do, by using this
+ * empty function as the bus type suspend callaback for SDIO.
+ */
+ return 0;
+}
+#endif
+
static const struct dev_pm_ops sdio_bus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
@@ -258,8 +272,7 @@ static void sdio_release_func(struct device *dev)
sdio_free_func_cis(func);
- if (func->info)
- kfree(func->info);
+ kfree(func->info);
kfree(func);
}
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 8f6f5ac131fc..78cb4d5d9d58 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -188,8 +188,7 @@ EXPORT_SYMBOL_GPL(sdio_set_block_size);
*/
static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
{
- unsigned mval = min(func->card->host->max_seg_size,
- func->card->host->max_blk_size);
+ unsigned mval = func->card->host->max_blk_size;
if (mmc_blksz_for_byte_mode(func->card))
mval = min(mval, func->cur_blksize);
@@ -311,11 +310,8 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
/* Do the bulk of the transfer using block mode (if supported). */
if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
/* Blocks per command is limited by host count, host transfer
- * size (we only use a single sg entry) and the maximum for
- * IO_RW_EXTENDED of 511 blocks. */
- max_blocks = min(func->card->host->max_blk_count,
- func->card->host->max_seg_size / func->cur_blksize);
- max_blocks = min(max_blocks, 511u);
+ * size and the maximum for IO_RW_EXTENDED of 511 blocks. */
+ max_blocks = min(func->card->host->max_blk_count, 511u);
while (remainder >= func->cur_blksize) {
unsigned blocks;
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index d29e20630eed..62508b457c4f 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -124,7 +124,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
- struct scatterlist sg;
+ struct scatterlist sg, *sg_ptr;
+ struct sg_table sgtable;
+ unsigned int nents, left_size, i;
+ unsigned int seg_size = card->host->max_seg_size;
BUG_ON(!card);
BUG_ON(fn > 7);
@@ -152,15 +155,36 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
/* Code in host drivers/fwk assumes that "blocks" always is >=1 */
data.blocks = blocks ? blocks : 1;
data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
- data.sg = &sg;
- data.sg_len = 1;
- sg_init_one(&sg, buf, data.blksz * data.blocks);
+ left_size = data.blksz * data.blocks;
+ nents = (left_size - 1) / seg_size + 1;
+ if (nents > 1) {
+ if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
+ return -ENOMEM;
+
+ data.sg = sgtable.sgl;
+ data.sg_len = nents;
+
+ for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
+ sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
+ min(seg_size, left_size),
+ offset_in_page(buf + (i * seg_size)));
+ left_size = left_size - seg_size;
+ }
+ } else {
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ sg_init_one(&sg, buf, left_size);
+ }
mmc_set_data_timeout(&data, card);
mmc_wait_for_req(card->host, &mrq);
+ if (nents > 1)
+ sg_free_table(&sgtable);
+
if (cmd.error)
return cmd.error;
if (data.error)
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 08c6b3dfe080..16a1c0b6f264 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -27,7 +27,13 @@ struct mmc_gpio {
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
/* Schedule a card detection after a debounce timeout */
- mmc_detect_change(dev_id, msecs_to_jiffies(100));
+ struct mmc_host *host = dev_id;
+
+ if (host->ops->card_event)
+ host->ops->card_event(host);
+
+ mmc_detect_change(host, msecs_to_jiffies(200));
+
return IRQ_HANDLED;
}
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9bf10e7bbfaf..737e4edc241b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -81,6 +81,18 @@ config MMC_RICOH_MMC
If unsure, say Y.
+config MMC_SDHCI_ACPI
+ tristate "SDHCI support for ACPI enumerated SDHCI controllers"
+ depends on MMC_SDHCI && ACPI
+ help
+ This selects support for ACPI enumerated SDHCI controllers,
+ identified by ACPI Compatibility ID PNP0D40 or specific
+ ACPI Hardware IDs.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
config MMC_SDHCI_PLTFM
tristate "SDHCI platform and OF driver helper"
depends on MMC_SDHCI
@@ -270,26 +282,8 @@ config MMC_AU1X
If unsure, say N.
-choice
- prompt "Atmel SD/MMC Driver"
- depends on AVR32 || ARCH_AT91
- default MMC_ATMELMCI if AVR32
- help
- Choose which driver to use for the Atmel MCI Silicon
-
-config MMC_AT91
- tristate "AT91 SD/MMC Card Interface support (DEPRECATED)"
- depends on ARCH_AT91
- help
- This selects the AT91 MCI controller. This driver will
- be removed soon (for more information have a look to
- Documentation/feature-removal-schedule.txt). Please use
- MMC_ATMEL_MCI.
-
- If unsure, say N.
-
config MMC_ATMELMCI
- tristate "Atmel Multimedia Card Interface support"
+ tristate "Atmel SD/MMC Driver (Multimedia Card Interface)"
depends on AVR32 || ARCH_AT91
help
This selects the Atmel Multimedia Card Interface driver. If
@@ -298,8 +292,6 @@ config MMC_ATMELMCI
If unsure, say N.
-endchoice
-
config MMC_ATMELMCI_DMA
bool "Atmel MCI DMA support"
depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
@@ -621,3 +613,21 @@ config MMC_USHC
Note: These controllers only support SDIO cards and do not
support MMC or SD memory cards.
+
+config MMC_WMT
+ tristate "Wondermedia SD/MMC Host Controller support"
+ depends on ARCH_VT8500
+ default y
+ help
+ This selects support for the SD/MMC Host Controller on
+ Wondermedia WM8505/WM8650 based SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wmt-sdmmc.
+
+config MMC_REALTEK_PCI
+ tristate "Realtek PCI-E SD/MMC Card Interface Driver"
+ depends on MFD_RTSX_PCI
+ help
+ Say Y here to include driver code to support SD/MMC card interface
+ of Realtek PCI-E card reader
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 17ad0a7ba40b..b648058d7182 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o
+obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o
obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
@@ -17,7 +18,6 @@ obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
-obj-$(CONFIG_MMC_AT91) += at91_mci.o
obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
obj-$(CONFIG_MMC_MSM) += msm_sdcc.o
@@ -45,6 +45,9 @@ obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o
obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
obj-$(CONFIG_MMC_VUB300) += vub300.o
obj-$(CONFIG_MMC_USHC) += ushc.o
+obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
+
+obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
deleted file mode 100644
index 74bed0fc23e7..000000000000
--- a/drivers/mmc/host/at91_mci.c
+++ /dev/null
@@ -1,1219 +0,0 @@
-/*
- * linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
- *
- * Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
- *
- * Copyright (C) 2006 Malcolm Noyes
- *
- * This program is free software; you can 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 is the AT91 MCI driver that has been tested with both MMC cards
- and SD-cards. Boards that support write protect are now supported.
- The CCAT91SBC001 board does not support SD cards.
-
- The three entry points are at91_mci_request, at91_mci_set_ios
- and at91_mci_get_ro.
-
- SET IOS
- This configures the device to put it into the correct mode and clock speed
- required.
-
- MCI REQUEST
- MCI request processes the commands sent in the mmc_request structure. This
- can consist of a processing command and a stop command in the case of
- multiple block transfers.
-
- There are three main types of request, commands, reads and writes.
-
- Commands are straight forward. The command is submitted to the controller and
- the request function returns. When the controller generates an interrupt to indicate
- the command is finished, the response to the command are read and the mmc_request_done
- function called to end the request.
-
- Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
- controller to manage the transfers.
-
- A read is done from the controller directly to the scatterlist passed in from the request.
- Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
- swapped in the scatterlist buffers. AT91SAM926x are not affected by this bug.
-
- The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
-
- A write is slightly different in that the bytes to write are read from the scatterlist
- into a dma memory buffer (this is in case the source buffer should be read only). The
- entire write buffer is then done from this single dma memory buffer.
-
- The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
-
- GET RO
- Gets the status of the write protect pin, if available.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-#include <linux/gfp.h>
-#include <linux/highmem.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/gpio.h>
-
-#include <mach/board.h>
-#include <mach/cpu.h>
-
-#include "at91_mci.h"
-
-#define DRIVER_NAME "at91_mci"
-
-static inline int at91mci_is_mci1rev2xx(void)
-{
- return ( cpu_is_at91sam9260()
- || cpu_is_at91sam9263()
- || cpu_is_at91sam9rl()
- || cpu_is_at91sam9g10()
- || cpu_is_at91sam9g20()
- );
-}
-
-#define FL_SENT_COMMAND (1 << 0)
-#define FL_SENT_STOP (1 << 1)
-
-#define AT91_MCI_ERRORS (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE \
- | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE \
- | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
-
-#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
-#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
-
-#define MCI_BLKSIZE 512
-#define MCI_MAXBLKSIZE 4095
-#define MCI_BLKATONCE 256
-#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
-
-/*
- * Low level type for this driver
- */
-struct at91mci_host
-{
- struct mmc_host *mmc;
- struct mmc_command *cmd;
- struct mmc_request *request;
-
- void __iomem *baseaddr;
- int irq;
-
- struct at91_mmc_data *board;
- int present;
-
- struct clk *mci_clk;
-
- /*
- * Flag indicating when the command has been sent. This is used to
- * work out whether or not to send the stop
- */
- unsigned int flags;
- /* flag for current bus settings */
- u32 bus_mode;
-
- /* DMA buffer used for transmitting */
- unsigned int* buffer;
- dma_addr_t physical_address;
- unsigned int total_length;
-
- /* Latest in the scatterlist that has been enabled for transfer, but not freed */
- int in_use_index;
-
- /* Latest in the scatterlist that has been enabled for transfer */
- int transfer_index;
-
- /* Timer for timeouts */
- struct timer_list timer;
-};
-
-/*
- * Reset the controller and restore most of the state
- */
-static void at91_reset_host(struct at91mci_host *host)
-{
- unsigned long flags;
- u32 mr;
- u32 sdcr;
- u32 dtor;
- u32 imr;
-
- local_irq_save(flags);
- imr = at91_mci_read(host, AT91_MCI_IMR);
-
- at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-
- /* save current state */
- mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
- sdcr = at91_mci_read(host, AT91_MCI_SDCR);
- dtor = at91_mci_read(host, AT91_MCI_DTOR);
-
- /* reset the controller */
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-
- /* restore state */
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
- at91_mci_write(host, AT91_MCI_MR, mr);
- at91_mci_write(host, AT91_MCI_SDCR, sdcr);
- at91_mci_write(host, AT91_MCI_DTOR, dtor);
- at91_mci_write(host, AT91_MCI_IER, imr);
-
- /* make sure sdio interrupts will fire */
- at91_mci_read(host, AT91_MCI_SR);
-
- local_irq_restore(flags);
-}
-
-static void at91_timeout_timer(unsigned long data)
-{
- struct at91mci_host *host;
-
- host = (struct at91mci_host *)data;
-
- if (host->request) {
- dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
-
- if (host->cmd && host->cmd->data) {
- host->cmd->data->error = -ETIMEDOUT;
- } else {
- if (host->cmd)
- host->cmd->error = -ETIMEDOUT;
- else
- host->request->cmd->error = -ETIMEDOUT;
- }
-
- at91_reset_host(host);
- mmc_request_done(host->mmc, host->request);
- }
-}
-
-/*
- * Copy from sg to a dma block - used for transfers
- */
-static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
-{
- unsigned int len, i, size;
- unsigned *dmabuf = host->buffer;
-
- size = data->blksz * data->blocks;
- len = data->sg_len;
-
- /* MCI1 rev2xx Data Write Operation and number of bytes erratum */
- if (at91mci_is_mci1rev2xx())
- if (host->total_length == 12)
- memset(dmabuf, 0, 12);
-
- /*
- * Just loop through all entries. Size might not
- * be the entire list though so make sure that
- * we do not transfer too much.
- */
- for (i = 0; i < len; i++) {
- struct scatterlist *sg;
- int amount;
- unsigned int *sgbuffer;
-
- sg = &data->sg[i];
-
- sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
- amount = min(size, sg->length);
- size -= amount;
-
- if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
- int index;
-
- for (index = 0; index < (amount / 4); index++)
- *dmabuf++ = swab32(sgbuffer[index]);
- } else {
- char *tmpv = (char *)dmabuf;
- memcpy(tmpv, sgbuffer, amount);
- tmpv += amount;
- dmabuf = (unsigned *)tmpv;
- }
-
- kunmap_atomic(sgbuffer);
-
- if (size == 0)
- break;
- }
-
- /*
- * Check that we didn't get a request to transfer
- * more data than can fit into the SG list.
- */
- BUG_ON(size != 0);
-}
-
-/*
- * Handle after a dma read
- */
-static void at91_mci_post_dma_read(struct at91mci_host *host)
-{
- struct mmc_command *cmd;
- struct mmc_data *data;
- unsigned int len, i, size;
- unsigned *dmabuf = host->buffer;
-
- pr_debug("post dma read\n");
-
- cmd = host->cmd;
- if (!cmd) {
- pr_debug("no command\n");
- return;
- }
-
- data = cmd->data;
- if (!data) {
- pr_debug("no data\n");
- return;
- }
-
- size = data->blksz * data->blocks;
- len = data->sg_len;
-
- at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-
- for (i = 0; i < len; i++) {
- struct scatterlist *sg;
- int amount;
- unsigned int *sgbuffer;
-
- sg = &data->sg[i];
-
- sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
- amount = min(size, sg->length);
- size -= amount;
-
- if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
- int index;
- for (index = 0; index < (amount / 4); index++)
- sgbuffer[index] = swab32(*dmabuf++);
- } else {
- char *tmpv = (char *)dmabuf;
- memcpy(sgbuffer, tmpv, amount);
- tmpv += amount;
- dmabuf = (unsigned *)tmpv;
- }
-
- flush_kernel_dcache_page(sg_page(sg));
- kunmap_atomic(sgbuffer);
- data->bytes_xfered += amount;
- if (size == 0)
- break;
- }
-
- pr_debug("post dma read done\n");
-}
-
-/*
- * Handle transmitted data
- */
-static void at91_mci_handle_transmitted(struct at91mci_host *host)
-{
- struct mmc_command *cmd;
- struct mmc_data *data;
-
- pr_debug("Handling the transmit\n");
-
- /* Disable the transfer */
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
- /* Now wait for cmd ready */
- at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-
- cmd = host->cmd;
- if (!cmd) return;
-
- data = cmd->data;
- if (!data) return;
-
- if (cmd->data->blocks > 1) {
- pr_debug("multiple write : wait for BLKE...\n");
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
- } else
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-}
-
-/*
- * Update bytes transfered count during a write operation
- */
-static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
-{
- struct mmc_data *data;
-
- /* always deal with the effective request (and not the current cmd) */
-
- if (host->request->cmd && host->request->cmd->error != 0)
- return;
-
- if (host->request->data) {
- data = host->request->data;
- if (data->flags & MMC_DATA_WRITE) {
- /* card is in IDLE mode now */
- pr_debug("-> bytes_xfered %d, total_length = %d\n",
- data->bytes_xfered, host->total_length);
- data->bytes_xfered = data->blksz * data->blocks;
- }
- }
-}
-
-
-/*Handle after command sent ready*/
-static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
-{
- if (!host->cmd)
- return 1;
- else if (!host->cmd->data) {
- if (host->flags & FL_SENT_STOP) {
- /*After multi block write, we must wait for NOTBUSY*/
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
- } else return 1;
- } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
- /*After sendding multi-block-write command, start DMA transfer*/
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
- }
-
- /* command not completed, have to wait */
- return 0;
-}
-
-
-/*
- * Enable the controller
- */
-static void at91_mci_enable(struct at91mci_host *host)
-{
- unsigned int mr;
-
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
- at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
- at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
- mr = AT91_MCI_PDCMODE | 0x34a;
-
- if (at91mci_is_mci1rev2xx())
- mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
-
- at91_mci_write(host, AT91_MCI_MR, mr);
-
- /* use Slot A or B (only one at same time) */
- at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
-}
-
-/*
- * Disable the controller
- */
-static void at91_mci_disable(struct at91mci_host *host)
-{
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-}
-
-/*
- * Send a command
- */
-static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
- unsigned int cmdr, mr;
- unsigned int block_length;
- struct mmc_data *data = cmd->data;
-
- unsigned int blocks;
- unsigned int ier = 0;
-
- host->cmd = cmd;
-
- /* Needed for leaving busy state before CMD1 */
- if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
- pr_debug("Clearing timeout\n");
- at91_mci_write(host, AT91_MCI_ARGR, 0);
- at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
- while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
- /* spin */
- pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
- }
- }
-
- cmdr = cmd->opcode;
-
- if (mmc_resp_type(cmd) == MMC_RSP_NONE)
- cmdr |= AT91_MCI_RSPTYP_NONE;
- else {
- /* if a response is expected then allow maximum response latancy */
- cmdr |= AT91_MCI_MAXLAT;
- /* set 136 bit response for R2, 48 bit response otherwise */
- if (mmc_resp_type(cmd) == MMC_RSP_R2)
- cmdr |= AT91_MCI_RSPTYP_136;
- else
- cmdr |= AT91_MCI_RSPTYP_48;
- }
-
- if (data) {
-
- if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
- if (data->blksz & 0x3) {
- pr_debug("Unsupported block size\n");
- cmd->error = -EINVAL;
- mmc_request_done(host->mmc, host->request);
- return;
- }
- if (data->flags & MMC_DATA_STREAM) {
- pr_debug("Stream commands not supported\n");
- cmd->error = -EINVAL;
- mmc_request_done(host->mmc, host->request);
- return;
- }
- }
-
- block_length = data->blksz;
- blocks = data->blocks;
-
- /* always set data start - also set direction flag for read */
- if (data->flags & MMC_DATA_READ)
- cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
- else if (data->flags & MMC_DATA_WRITE)
- cmdr |= AT91_MCI_TRCMD_START;
-
- if (cmd->opcode == SD_IO_RW_EXTENDED) {
- cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
- } else {
- if (data->flags & MMC_DATA_STREAM)
- cmdr |= AT91_MCI_TRTYP_STREAM;
- if (data->blocks > 1)
- cmdr |= AT91_MCI_TRTYP_MULTIPLE;
- }
- }
- else {
- block_length = 0;
- blocks = 0;
- }
-
- if (host->flags & FL_SENT_STOP)
- cmdr |= AT91_MCI_TRCMD_STOP;
-
- if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
- cmdr |= AT91_MCI_OPDCMD;
-
- /*
- * Set the arguments and send the command
- */
- pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
- cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
-
- if (!data) {
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
- at91_mci_write(host, ATMEL_PDC_RPR, 0);
- at91_mci_write(host, ATMEL_PDC_RCR, 0);
- at91_mci_write(host, ATMEL_PDC_RNPR, 0);
- at91_mci_write(host, ATMEL_PDC_RNCR, 0);
- at91_mci_write(host, ATMEL_PDC_TPR, 0);
- at91_mci_write(host, ATMEL_PDC_TCR, 0);
- at91_mci_write(host, ATMEL_PDC_TNPR, 0);
- at91_mci_write(host, ATMEL_PDC_TNCR, 0);
- ier = AT91_MCI_CMDRDY;
- } else {
- /* zero block length and PDC mode */
- mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
- mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
- mr |= (block_length << 16);
- mr |= AT91_MCI_PDCMODE;
- at91_mci_write(host, AT91_MCI_MR, mr);
-
- if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
- at91_mci_write(host, AT91_MCI_BLKR,
- AT91_MCI_BLKR_BCNT(blocks) |
- AT91_MCI_BLKR_BLKLEN(block_length));
-
- /*
- * Disable the PDC controller
- */
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
- if (cmdr & AT91_MCI_TRCMD_START) {
- data->bytes_xfered = 0;
- host->transfer_index = 0;
- host->in_use_index = 0;
- if (cmdr & AT91_MCI_TRDIR) {
- /*
- * Handle a read
- */
- host->total_length = 0;
-
- at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
- at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
- (blocks * block_length) : (blocks * block_length) / 4);
- at91_mci_write(host, ATMEL_PDC_RNPR, 0);
- at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-
- ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
- }
- else {
- /*
- * Handle a write
- */
- host->total_length = block_length * blocks;
- /*
- * MCI1 rev2xx Data Write Operation and
- * number of bytes erratum
- */
- if (at91mci_is_mci1rev2xx())
- if (host->total_length < 12)
- host->total_length = 12;
-
- at91_mci_sg_to_dma(host, data);
-
- pr_debug("Transmitting %d bytes\n", host->total_length);
-
- at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
- at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
- host->total_length : host->total_length / 4);
-
- ier = AT91_MCI_CMDRDY;
- }
- }
- }
-
- /*
- * Send the command and then enable the PDC - not the other way round as
- * the data sheet says
- */
-
- at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
- at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-
- if (cmdr & AT91_MCI_TRCMD_START) {
- if (cmdr & AT91_MCI_TRDIR)
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
- }
-
- /* Enable selected interrupts */
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
-}
-
-/*
- * Process the next step in the request
- */
-static void at91_mci_process_next(struct at91mci_host *host)
-{
- if (!(host->flags & FL_SENT_COMMAND)) {
- host->flags |= FL_SENT_COMMAND;
- at91_mci_send_command(host, host->request->cmd);
- }
- else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
- host->flags |= FL_SENT_STOP;
- at91_mci_send_command(host, host->request->stop);
- } else {
- del_timer(&host->timer);
- /* the at91rm9200 mci controller hangs after some transfers,
- * and the workaround is to reset it after each transfer.
- */
- if (cpu_is_at91rm9200())
- at91_reset_host(host);
- mmc_request_done(host->mmc, host->request);
- }
-}
-
-/*
- * Handle a command that has been completed
- */
-static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
-{
- struct mmc_command *cmd = host->cmd;
- struct mmc_data *data = cmd->data;
-
- at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
- cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
- cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
- cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
- cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
-
- pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
- status, at91_mci_read(host, AT91_MCI_SR),
- cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
- if (status & AT91_MCI_ERRORS) {
- if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
- cmd->error = 0;
- }
- else {
- if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
- if (data) {
- if (status & AT91_MCI_DTOE)
- data->error = -ETIMEDOUT;
- else if (status & AT91_MCI_DCRCE)
- data->error = -EILSEQ;
- }
- } else {
- if (status & AT91_MCI_RTOE)
- cmd->error = -ETIMEDOUT;
- else if (status & AT91_MCI_RCRCE)
- cmd->error = -EILSEQ;
- else
- cmd->error = -EIO;
- }
-
- pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
- cmd->error, data ? data->error : 0,
- cmd->opcode, cmd->retries);
- }
- }
- else
- cmd->error = 0;
-
- at91_mci_process_next(host);
-}
-
-/*
- * Handle an MMC request
- */
-static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
- struct at91mci_host *host = mmc_priv(mmc);
- host->request = mrq;
- host->flags = 0;
-
- /* more than 1s timeout needed with slow SD cards */
- mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
-
- at91_mci_process_next(host);
-}
-
-/*
- * Set the IOS
- */
-static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
- int clkdiv;
- struct at91mci_host *host = mmc_priv(mmc);
- unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
-
- host->bus_mode = ios->bus_mode;
-
- if (ios->clock == 0) {
- /* Disable the MCI controller */
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
- clkdiv = 0;
- }
- else {
- /* Enable the MCI controller */
- at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-
- if ((at91_master_clock % (ios->clock * 2)) == 0)
- clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
- else
- clkdiv = (at91_master_clock / ios->clock) / 2;
-
- pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
- at91_master_clock / (2 * (clkdiv + 1)));
- }
- if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
- pr_debug("MMC: Setting controller bus width to 4\n");
- at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
- }
- else {
- pr_debug("MMC: Setting controller bus width to 1\n");
- at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
- }
-
- /* Set the clock divider */
- at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
-
- /* maybe switch power to the card */
- if (gpio_is_valid(host->board->vcc_pin)) {
- switch (ios->power_mode) {
- case MMC_POWER_OFF:
- gpio_set_value(host->board->vcc_pin, 0);
- break;
- case MMC_POWER_UP:
- gpio_set_value(host->board->vcc_pin, 1);
- break;
- case MMC_POWER_ON:
- break;
- default:
- WARN_ON(1);
- }
- }
-}
-
-/*
- * Handle an interrupt
- */
-static irqreturn_t at91_mci_irq(int irq, void *devid)
-{
- struct at91mci_host *host = devid;
- int completed = 0;
- unsigned int int_status, int_mask;
-
- int_status = at91_mci_read(host, AT91_MCI_SR);
- int_mask = at91_mci_read(host, AT91_MCI_IMR);
-
- pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
- int_status & int_mask);
-
- int_status = int_status & int_mask;
-
- if (int_status & AT91_MCI_ERRORS) {
- completed = 1;
-
- if (int_status & AT91_MCI_UNRE)
- pr_debug("MMC: Underrun error\n");
- if (int_status & AT91_MCI_OVRE)
- pr_debug("MMC: Overrun error\n");
- if (int_status & AT91_MCI_DTOE)
- pr_debug("MMC: Data timeout\n");
- if (int_status & AT91_MCI_DCRCE)
- pr_debug("MMC: CRC error in data\n");
- if (int_status & AT91_MCI_RTOE)
- pr_debug("MMC: Response timeout\n");
- if (int_status & AT91_MCI_RENDE)
- pr_debug("MMC: Response end bit error\n");
- if (int_status & AT91_MCI_RCRCE)
- pr_debug("MMC: Response CRC error\n");
- if (int_status & AT91_MCI_RDIRE)
- pr_debug("MMC: Response direction error\n");
- if (int_status & AT91_MCI_RINDE)
- pr_debug("MMC: Response index error\n");
- } else {
- /* Only continue processing if no errors */
-
- if (int_status & AT91_MCI_TXBUFE) {
- pr_debug("TX buffer empty\n");
- at91_mci_handle_transmitted(host);
- }
-
- if (int_status & AT91_MCI_ENDRX) {
- pr_debug("ENDRX\n");
- at91_mci_post_dma_read(host);
- }
-
- if (int_status & AT91_MCI_RXBUFF) {
- pr_debug("RX buffer full\n");
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
- at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
- completed = 1;
- }
-
- if (int_status & AT91_MCI_ENDTX)
- pr_debug("Transmit has ended\n");
-
- if (int_status & AT91_MCI_NOTBUSY) {
- pr_debug("Card is ready\n");
- at91_mci_update_bytes_xfered(host);
- completed = 1;
- }
-
- if (int_status & AT91_MCI_DTIP)
- pr_debug("Data transfer in progress\n");
-
- if (int_status & AT91_MCI_BLKE) {
- pr_debug("Block transfer has ended\n");
- if (host->request->data && host->request->data->blocks > 1) {
- /* multi block write : complete multi write
- * command and send stop */
- completed = 1;
- } else {
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
- }
- }
-
- if (int_status & AT91_MCI_SDIOIRQA)
- mmc_signal_sdio_irq(host->mmc);
-
- if (int_status & AT91_MCI_SDIOIRQB)
- mmc_signal_sdio_irq(host->mmc);
-
- if (int_status & AT91_MCI_TXRDY)
- pr_debug("Ready to transmit\n");
-
- if (int_status & AT91_MCI_RXRDY)
- pr_debug("Ready to receive\n");
-
- if (int_status & AT91_MCI_CMDRDY) {
- pr_debug("Command ready\n");
- completed = at91_mci_handle_cmdrdy(host);
- }
- }
-
- if (completed) {
- pr_debug("Completed command\n");
- at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
- at91_mci_completed_command(host, int_status);
- } else
- at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
-{
- struct at91mci_host *host = _host;
- int present;
-
- /* entering this ISR means that we have configured det_pin:
- * we can use its value in board structure */
- present = !gpio_get_value(host->board->det_pin);
-
- /*
- * we expect this irq on both insert and remove,
- * and use a short delay to debounce.
- */
- if (present != host->present) {
- host->present = present;
- pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
- present ? "insert" : "remove");
- if (!present) {
- pr_debug("****** Resetting SD-card bus width ******\n");
- at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
- }
- /* 0.5s needed because of early card detect switch firing */
- mmc_detect_change(host->mmc, msecs_to_jiffies(500));
- }
- return IRQ_HANDLED;
-}
-
-static int at91_mci_get_ro(struct mmc_host *mmc)
-{
- struct at91mci_host *host = mmc_priv(mmc);
-
- if (gpio_is_valid(host->board->wp_pin))
- return !!gpio_get_value(host->board->wp_pin);
- /*
- * Board doesn't support read only detection; let the mmc core
- * decide what to do.
- */
- return -ENOSYS;
-}
-
-static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
- struct at91mci_host *host = mmc_priv(mmc);
-
- pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
- host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
- at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
- host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
-
-}
-
-static const struct mmc_host_ops at91_mci_ops = {
- .request = at91_mci_request,
- .set_ios = at91_mci_set_ios,
- .get_ro = at91_mci_get_ro,
- .enable_sdio_irq = at91_mci_enable_sdio_irq,
-};
-
-/*
- * Probe for the device
- */
-static int __init at91_mci_probe(struct platform_device *pdev)
-{
- struct mmc_host *mmc;
- struct at91mci_host *host;
- struct resource *res;
- int ret;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENXIO;
-
- if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME))
- return -EBUSY;
-
- mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
- if (!mmc) {
- ret = -ENOMEM;
- dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
- goto fail6;
- }
-
- mmc->ops = &at91_mci_ops;
- mmc->f_min = 375000;
- mmc->f_max = 25000000;
- mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps = 0;
-
- mmc->max_blk_size = MCI_MAXBLKSIZE;
- mmc->max_blk_count = MCI_BLKATONCE;
- mmc->max_req_size = MCI_BUFSIZE;
- mmc->max_segs = MCI_BLKATONCE;
- mmc->max_seg_size = MCI_BUFSIZE;
-
- host = mmc_priv(mmc);
- host->mmc = mmc;
- host->bus_mode = 0;
- host->board = pdev->dev.platform_data;
- if (host->board->wire4) {
- if (at91mci_is_mci1rev2xx())
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- else
- dev_warn(&pdev->dev, "4 wire bus mode not supported"
- " - using 1 wire\n");
- }
-
- host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
- &host->physical_address, GFP_KERNEL);
- if (!host->buffer) {
- ret = -ENOMEM;
- dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
- goto fail5;
- }
-
- /* Add SDIO capability when available */
- if (at91mci_is_mci1rev2xx()) {
- /* at91mci MCI1 rev2xx sdio interrupt erratum */
- if (host->board->wire4 || !host->board->slot_b)
- mmc->caps |= MMC_CAP_SDIO_IRQ;
- }
-
- /*
- * Reserve GPIOs ... board init code makes sure these pins are set
- * up as GPIOs with the right direction (input, except for vcc)
- */
- if (gpio_is_valid(host->board->det_pin)) {
- ret = gpio_request(host->board->det_pin, "mmc_detect");
- if (ret < 0) {
- dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
- goto fail4b;
- }
- }
- if (gpio_is_valid(host->board->wp_pin)) {
- ret = gpio_request(host->board->wp_pin, "mmc_wp");
- if (ret < 0) {
- dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
- goto fail4;
- }
- }
- if (gpio_is_valid(host->board->vcc_pin)) {
- ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
- if (ret < 0) {
- dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
- goto fail3;
- }
- }
-
- /*
- * Get Clock
- */
- host->mci_clk = clk_get(&pdev->dev, "mci_clk");
- if (IS_ERR(host->mci_clk)) {
- ret = -ENODEV;
- dev_dbg(&pdev->dev, "no mci_clk?\n");
- goto fail2;
- }
-
- /*
- * Map I/O region
- */
- host->baseaddr = ioremap(res->start, resource_size(res));
- if (!host->baseaddr) {
- ret = -ENOMEM;
- goto fail1;
- }
-
- /*
- * Reset hardware
- */
- clk_enable(host->mci_clk); /* Enable the peripheral clock */
- at91_mci_disable(host);
- at91_mci_enable(host);
-
- /*
- * Allocate the MCI interrupt
- */
- host->irq = platform_get_irq(pdev, 0);
- ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
- mmc_hostname(mmc), host);
- if (ret) {
- dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
- goto fail0;
- }
-
- setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
-
- platform_set_drvdata(pdev, mmc);
-
- /*
- * Add host to MMC layer
- */
- if (gpio_is_valid(host->board->det_pin)) {
- host->present = !gpio_get_value(host->board->det_pin);
- }
- else
- host->present = -1;
-
- mmc_add_host(mmc);
-
- /*
- * monitor card insertion/removal if we can
- */
- if (gpio_is_valid(host->board->det_pin)) {
- ret = request_irq(gpio_to_irq(host->board->det_pin),
- at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
- if (ret)
- dev_warn(&pdev->dev, "request MMC detect irq failed\n");
- else
- device_init_wakeup(&pdev->dev, 1);
- }
-
- pr_debug("Added MCI driver\n");
-
- return 0;
-
-fail0:
- clk_disable(host->mci_clk);
- iounmap(host->baseaddr);
-fail1:
- clk_put(host->mci_clk);
-fail2:
- if (gpio_is_valid(host->board->vcc_pin))
- gpio_free(host->board->vcc_pin);
-fail3:
- if (gpio_is_valid(host->board->wp_pin))
- gpio_free(host->board->wp_pin);
-fail4:
- if (gpio_is_valid(host->board->det_pin))
- gpio_free(host->board->det_pin);
-fail4b:
- if (host->buffer)
- dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
- host->buffer, host->physical_address);
-fail5:
- mmc_free_host(mmc);
-fail6:
- release_mem_region(res->start, resource_size(res));
- dev_err(&pdev->dev, "probe failed, err %d\n", ret);
- return ret;
-}
-
-/*
- * Remove a device
- */
-static int __exit at91_mci_remove(struct platform_device *pdev)
-{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct at91mci_host *host;
- struct resource *res;
-
- if (!mmc)
- return -1;
-
- host = mmc_priv(mmc);
-
- if (host->buffer)
- dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
- host->buffer, host->physical_address);
-
- if (gpio_is_valid(host->board->det_pin)) {
- if (device_can_wakeup(&pdev->dev))
- free_irq(gpio_to_irq(host->board->det_pin), host);
- device_init_wakeup(&pdev->dev, 0);
- gpio_free(host->board->det_pin);
- }
-
- at91_mci_disable(host);
- del_timer_sync(&host->timer);
- mmc_remove_host(mmc);
- free_irq(host->irq, host);
-
- clk_disable(host->mci_clk); /* Disable the peripheral clock */
- clk_put(host->mci_clk);
-
- if (gpio_is_valid(host->board->vcc_pin))
- gpio_free(host->board->vcc_pin);
- if (gpio_is_valid(host->board->wp_pin))
- gpio_free(host->board->wp_pin);
-
- iounmap(host->baseaddr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- mmc_free_host(mmc);
- platform_set_drvdata(pdev, NULL);
- pr_debug("MCI Removed\n");
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct at91mci_host *host = mmc_priv(mmc);
- int ret = 0;
-
- if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
- enable_irq_wake(host->board->det_pin);
-
- if (mmc)
- ret = mmc_suspend_host(mmc);
-
- return ret;
-}
-
-static int at91_mci_resume(struct platform_device *pdev)
-{
- struct mmc_host *mmc = platform_get_drvdata(pdev);
- struct at91mci_host *host = mmc_priv(mmc);
- int ret = 0;
-
- if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
- disable_irq_wake(host->board->det_pin);
-
- if (mmc)
- ret = mmc_resume_host(mmc);
-
- return ret;
-}
-#else
-#define at91_mci_suspend NULL
-#define at91_mci_resume NULL
-#endif
-
-static struct platform_driver at91_mci_driver = {
- .remove = __exit_p(at91_mci_remove),
- .suspend = at91_mci_suspend,
- .resume = at91_mci_resume,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init at91_mci_init(void)
-{
- return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
-}
-
-static void __exit at91_mci_exit(void)
-{
- platform_driver_unregister(&at91_mci_driver);
-}
-
-module_init(at91_mci_init);
-module_exit(at91_mci_exit);
-
-MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
-MODULE_AUTHOR("Nick Randell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_mci");
diff --git a/drivers/mmc/host/at91_mci.h b/drivers/mmc/host/at91_mci.h
deleted file mode 100644
index eec3a6b1c2bc..000000000000
--- a/drivers/mmc/host/at91_mci.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * drivers/mmc/host/at91_mci.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision F.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_MCI_H
-#define AT91_MCI_H
-
-#define AT91_MCI_CR 0x00 /* Control Register */
-#define AT91_MCI_MCIEN (1 << 0) /* Multi-Media Interface Enable */
-#define AT91_MCI_MCIDIS (1 << 1) /* Multi-Media Interface Disable */
-#define AT91_MCI_PWSEN (1 << 2) /* Power Save Mode Enable */
-#define AT91_MCI_PWSDIS (1 << 3) /* Power Save Mode Disable */
-#define AT91_MCI_SWRST (1 << 7) /* Software Reset */
-
-#define AT91_MCI_MR 0x04 /* Mode Register */
-#define AT91_MCI_CLKDIV (0xff << 0) /* Clock Divider */
-#define AT91_MCI_PWSDIV (7 << 8) /* Power Saving Divider */
-#define AT91_MCI_RDPROOF (1 << 11) /* Read Proof Enable [SAM926[03] only] */
-#define AT91_MCI_WRPROOF (1 << 12) /* Write Proof Enable [SAM926[03] only] */
-#define AT91_MCI_PDCFBYTE (1 << 13) /* PDC Force Byte Transfer [SAM926[03] only] */
-#define AT91_MCI_PDCPADV (1 << 14) /* PDC Padding Value */
-#define AT91_MCI_PDCMODE (1 << 15) /* PDC-orientated Mode */
-#define AT91_MCI_BLKLEN (0xfff << 18) /* Data Block Length */
-
-#define AT91_MCI_DTOR 0x08 /* Data Timeout Register */
-#define AT91_MCI_DTOCYC (0xf << 0) /* Data Timeout Cycle Number */
-#define AT91_MCI_DTOMUL (7 << 4) /* Data Timeout Multiplier */
-#define AT91_MCI_DTOMUL_1 (0 << 4)
-#define AT91_MCI_DTOMUL_16 (1 << 4)
-#define AT91_MCI_DTOMUL_128 (2 << 4)
-#define AT91_MCI_DTOMUL_256 (3 << 4)
-#define AT91_MCI_DTOMUL_1K (4 << 4)
-#define AT91_MCI_DTOMUL_4K (5 << 4)
-#define AT91_MCI_DTOMUL_64K (6 << 4)
-#define AT91_MCI_DTOMUL_1M (7 << 4)
-
-#define AT91_MCI_SDCR 0x0c /* SD Card Register */
-#define AT91_MCI_SDCSEL (3 << 0) /* SD Card Selector */
-#define AT91_MCI_SDCBUS (1 << 7) /* 1-bit or 4-bit bus */
-
-#define AT91_MCI_ARGR 0x10 /* Argument Register */
-
-#define AT91_MCI_CMDR 0x14 /* Command Register */
-#define AT91_MCI_CMDNB (0x3f << 0) /* Command Number */
-#define AT91_MCI_RSPTYP (3 << 6) /* Response Type */
-#define AT91_MCI_RSPTYP_NONE (0 << 6)
-#define AT91_MCI_RSPTYP_48 (1 << 6)
-#define AT91_MCI_RSPTYP_136 (2 << 6)
-#define AT91_MCI_SPCMD (7 << 8) /* Special Command */
-#define AT91_MCI_SPCMD_NONE (0 << 8)
-#define AT91_MCI_SPCMD_INIT (1 << 8)
-#define AT91_MCI_SPCMD_SYNC (2 << 8)
-#define AT91_MCI_SPCMD_ICMD (4 << 8)
-#define AT91_MCI_SPCMD_IRESP (5 << 8)
-#define AT91_MCI_OPDCMD (1 << 11) /* Open Drain Command */
-#define AT91_MCI_MAXLAT (1 << 12) /* Max Latency for Command to Response */
-#define AT91_MCI_TRCMD (3 << 16) /* Transfer Command */
-#define AT91_MCI_TRCMD_NONE (0 << 16)
-#define AT91_MCI_TRCMD_START (1 << 16)
-#define AT91_MCI_TRCMD_STOP (2 << 16)
-#define AT91_MCI_TRDIR (1 << 18) /* Transfer Direction */
-#define AT91_MCI_TRTYP (3 << 19) /* Transfer Type */
-#define AT91_MCI_TRTYP_BLOCK (0 << 19)
-#define AT91_MCI_TRTYP_MULTIPLE (1 << 19)
-#define AT91_MCI_TRTYP_STREAM (2 << 19)
-#define AT91_MCI_TRTYP_SDIO_BYTE (4 << 19)
-#define AT91_MCI_TRTYP_SDIO_BLOCK (5 << 19)
-
-#define AT91_MCI_BLKR 0x18 /* Block Register */
-#define AT91_MCI_BLKR_BCNT(n) ((0xffff & (n)) << 0) /* Block count */
-#define AT91_MCI_BLKR_BLKLEN(n) ((0xffff & (n)) << 16) /* Block length */
-
-#define AT91_MCI_RSPR(n) (0x20 + ((n) * 4)) /* Response Registers 0-3 */
-#define AT91_MCR_RDR 0x30 /* Receive Data Register */
-#define AT91_MCR_TDR 0x34 /* Transmit Data Register */
-
-#define AT91_MCI_SR 0x40 /* Status Register */
-#define AT91_MCI_CMDRDY (1 << 0) /* Command Ready */
-#define AT91_MCI_RXRDY (1 << 1) /* Receiver Ready */
-#define AT91_MCI_TXRDY (1 << 2) /* Transmit Ready */
-#define AT91_MCI_BLKE (1 << 3) /* Data Block Ended */
-#define AT91_MCI_DTIP (1 << 4) /* Data Transfer in Progress */
-#define AT91_MCI_NOTBUSY (1 << 5) /* Data Not Busy */
-#define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */
-#define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */
-#define AT91_MCI_SDIOIRQA (1 << 8) /* SDIO Interrupt for Slot A */
-#define AT91_MCI_SDIOIRQB (1 << 9) /* SDIO Interrupt for Slot B */
-#define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */
-#define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */
-#define AT91_MCI_RINDE (1 << 16) /* Response Index Error */
-#define AT91_MCI_RDIRE (1 << 17) /* Response Direction Error */
-#define AT91_MCI_RCRCE (1 << 18) /* Response CRC Error */
-#define AT91_MCI_RENDE (1 << 19) /* Response End Bit Error */
-#define AT91_MCI_RTOE (1 << 20) /* Response Time-out Error */
-#define AT91_MCI_DCRCE (1 << 21) /* Data CRC Error */
-#define AT91_MCI_DTOE (1 << 22) /* Data Time-out Error */
-#define AT91_MCI_OVRE (1 << 30) /* Overrun */
-#define AT91_MCI_UNRE (1 << 31) /* Underrun */
-
-#define AT91_MCI_IER 0x44 /* Interrupt Enable Register */
-#define AT91_MCI_IDR 0x48 /* Interrupt Disable Register */
-#define AT91_MCI_IMR 0x4c /* Interrupt Mask Register */
-
-#endif
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index ddf096e3803f..5248ba4369a3 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -511,7 +511,7 @@ static const struct of_device_id atmci_dt_ids[] = {
MODULE_DEVICE_TABLE(of, atmci_dt_ids);
-static struct mci_platform_data __devinit*
+static struct mci_platform_data*
atmci_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index dbd0c8a4e98a..127a8fade4da 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -943,7 +943,7 @@ static const struct mmc_host_ops au1xmmc_ops = {
.enable_sdio_irq = au1xmmc_enable_sdio_irq,
};
-static int __devinit au1xmmc_probe(struct platform_device *pdev)
+static int au1xmmc_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct au1xmmc_host *host;
@@ -1114,7 +1114,7 @@ out0:
return ret;
}
-static int __devexit au1xmmc_remove(struct platform_device *pdev)
+static int au1xmmc_remove(struct platform_device *pdev)
{
struct au1xmmc_host *host = platform_get_drvdata(pdev);
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index b9b463eca1ec..fb4348c5b6ac 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -522,7 +522,7 @@ static void sdh_reset(void)
SSYNC();
}
-static int __devinit sdh_probe(struct platform_device *pdev)
+static int sdh_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct sdh_host *host;
@@ -617,7 +617,7 @@ out1:
return ret;
}
-static int __devexit sdh_remove(struct platform_device *pdev)
+static int sdh_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
@@ -680,7 +680,7 @@ static int sdh_resume(struct platform_device *dev)
static struct platform_driver sdh_driver = {
.probe = sdh_probe,
- .remove = __devexit_p(sdh_remove),
+ .remove = sdh_remove,
.suspend = sdh_suspend,
.resume = sdh_resume,
.driver = {
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 83693fd7c6b3..777ca2046b27 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -690,7 +690,7 @@ static int cb710_mmc_resume(struct platform_device *pdev)
#endif /* CONFIG_PM */
-static int __devinit cb710_mmc_init(struct platform_device *pdev)
+static int cb710_mmc_init(struct platform_device *pdev)
{
struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
struct cb710_chip *chip = cb710_slot_to_chip(slot);
@@ -746,7 +746,7 @@ err_free_mmc:
return err;
}
-static int __devexit cb710_mmc_exit(struct platform_device *pdev)
+static int cb710_mmc_exit(struct platform_device *pdev)
{
struct cb710_slot *slot = cb710_pdev_to_slot(pdev);
struct mmc_host *mmc = cb710_slot_to_mmc(slot);
@@ -773,7 +773,7 @@ static int __devexit cb710_mmc_exit(struct platform_device *pdev)
static struct platform_driver cb710_mmc_driver = {
.driver.name = "cb710-mmc",
.probe = cb710_mmc_init,
- .remove = __devexit_p(cb710_mmc_exit),
+ .remove = cb710_mmc_exit,
#ifdef CONFIG_PM
.suspend = cb710_mmc_suspend,
.resume = cb710_mmc_resume,
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c
index edb37e9135ae..8ee0f74f9374 100644
--- a/drivers/mmc/host/dw_mmc-pci.c
+++ b/drivers/mmc/host/dw_mmc-pci.c
@@ -37,7 +37,7 @@ static struct dw_mci_board pci_board_data = {
.fifo_depth = 32,
};
-static int __devinit dw_mci_pci_probe(struct pci_dev *pdev,
+static int dw_mci_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *entries)
{
struct dw_mci *host;
@@ -85,7 +85,7 @@ err_disable_dev:
return ret;
}
-static void __devexit dw_mci_pci_remove(struct pci_dev *pdev)
+static void dw_mci_pci_remove(struct pci_dev *pdev)
{
struct dw_mci *host = pci_get_drvdata(pdev);
@@ -134,7 +134,7 @@ static struct pci_driver dw_mci_pci_driver = {
.name = "dw_mmc_pci",
.id_table = dw_mci_pci_id,
.probe = dw_mci_pci_probe,
- .remove = dw_mci_pci_remove,
+ .remove = __devexit_p(dw_mci_pci_remove),
.driver = {
.pm = &dw_mci_pci_pmops
},
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 917936bee5d5..222036c9e053 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -62,12 +62,12 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
-static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
+static int dw_mci_pltfm_probe(struct platform_device *pdev)
{
return dw_mci_pltfm_register(pdev, NULL);
}
-static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev)
+static int dw_mci_pltfm_remove(struct platform_device *pdev)
{
struct dw_mci *host = platform_get_drvdata(pdev);
@@ -119,7 +119,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = {
MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
static struct platform_driver dw_mci_pltfm_driver = {
- .remove = __exit_p(dw_mci_pltfm_remove),
+ .probe = dw_mci_pltfm_probe,
+ .remove = __devexit_p(dw_mci_pltfm_remove),
.driver = {
.name = "dw_mmc",
.of_match_table = of_match_ptr(dw_mci_pltfm_match),
@@ -127,18 +128,7 @@ static struct platform_driver dw_mci_pltfm_driver = {
},
};
-static int __init dw_mci_init(void)
-{
- return platform_driver_probe(&dw_mci_pltfm_driver, dw_mci_pltfm_probe);
-}
-
-static void __exit dw_mci_exit(void)
-{
- platform_driver_unregister(&dw_mci_pltfm_driver);
-}
-
-module_init(dw_mci_init);
-module_exit(dw_mci_exit);
+module_platform_driver(dw_mci_pltfm_driver);
MODULE_DESCRIPTION("DW Multimedia Card Interface driver");
MODULE_AUTHOR("NXP Semiconductor VietNam");
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
index 2ac37b81de4d..68e7fd2f6148 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.h
+++ b/drivers/mmc/host/dw_mmc-pltfm.h
@@ -14,7 +14,7 @@
extern int dw_mci_pltfm_register(struct platform_device *pdev,
const struct dw_mci_drv_data *drv_data);
-extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
+extern int dw_mci_pltfm_remove(struct platform_device *pdev);
extern const struct dev_pm_ops dw_mci_pltfm_pmops;
#endif /* _DW_MMC_PLTFM_H_ */
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index c0667c8af2bd..323c5022c2ca 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -232,7 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
{
struct mmc_data *data;
struct dw_mci_slot *slot = mmc_priv(mmc);
- struct dw_mci_drv_data *drv_data = slot->host->drv_data;
+ const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 cmdr;
cmd->error = -EINPROGRESS;
@@ -617,13 +617,13 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
cmd, arg, cmd_status);
}
-static void dw_mci_setup_bus(struct dw_mci_slot *slot)
+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
{
struct dw_mci *host = slot->host;
u32 div;
u32 clk_en_a;
- if (slot->clock != host->current_speed) {
+ if (slot->clock != host->current_speed || force_clkinit) {
div = host->bus_hz / slot->clock;
if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
/*
@@ -683,9 +683,6 @@ static void __dw_mci_start_request(struct dw_mci *host,
if (host->pdata->select_slot)
host->pdata->select_slot(slot->id);
- /* Slot specific timing and width adjustment */
- dw_mci_setup_bus(slot);
-
host->cur_slot = slot;
host->mrq = mrq;
@@ -773,22 +770,19 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
- struct dw_mci_drv_data *drv_data = slot->host->drv_data;
+ const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 regs;
- /* set default 1 bit mode */
- slot->ctype = SDMMC_CTYPE_1BIT;
-
switch (ios->bus_width) {
- case MMC_BUS_WIDTH_1:
- slot->ctype = SDMMC_CTYPE_1BIT;
- break;
case MMC_BUS_WIDTH_4:
slot->ctype = SDMMC_CTYPE_4BIT;
break;
case MMC_BUS_WIDTH_8:
slot->ctype = SDMMC_CTYPE_8BIT;
break;
+ default:
+ /* set default 1 bit mode */
+ slot->ctype = SDMMC_CTYPE_1BIT;
}
regs = mci_readl(slot->host, UHS_REG);
@@ -812,6 +806,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (drv_data && drv_data->set_ios)
drv_data->set_ios(slot->host, ios);
+ /* Slot specific timing and width adjustment */
+ dw_mci_setup_bus(slot, false);
+
switch (ios->power_mode) {
case MMC_POWER_UP:
set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
@@ -1817,7 +1814,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
{
struct mmc_host *mmc;
struct dw_mci_slot *slot;
- struct dw_mci_drv_data *drv_data = host->drv_data;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
int ctrl_id, ret;
u8 bus_width;
@@ -1850,6 +1847,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
if (host->pdata->caps)
mmc->caps = host->pdata->caps;
+ if (host->pdata->pm_caps)
+ mmc->pm_caps = host->pdata->pm_caps;
+
if (host->dev->of_node) {
ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
if (ctrl_id < 0)
@@ -1911,7 +1911,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
#endif /* CONFIG_MMC_DW_IDMAC */
}
- host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+ host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc");
if (IS_ERR(host->vmmc)) {
pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
host->vmmc = NULL;
@@ -1960,7 +1960,7 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
static void dw_mci_init_dma(struct dw_mci *host)
{
/* Alloc memory for sg translation */
- host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
+ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
if (!host->sg_cpu) {
dev_err(host->dev, "%s: could not alloc DMA memory\n",
@@ -2038,7 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
struct dw_mci_board *pdata;
struct device *dev = host->dev;
struct device_node *np = dev->of_node;
- struct dw_mci_drv_data *drv_data = host->drv_data;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
int idx, ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2072,6 +2072,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(ret);
}
+ if (of_find_property(np, "keep-power-in-suspend", NULL))
+ pdata->pm_caps |= MMC_PM_KEEP_POWER;
+
+ if (of_find_property(np, "enable-sdio-wakeup", NULL))
+ pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+
return pdata;
}
@@ -2084,7 +2090,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
int dw_mci_probe(struct dw_mci *host)
{
- struct dw_mci_drv_data *drv_data = host->drv_data;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
int width, i, ret = 0;
u32 fifo_size;
int init_slots = 0;
@@ -2103,26 +2109,24 @@ int dw_mci_probe(struct dw_mci *host)
return -ENODEV;
}
- host->biu_clk = clk_get(host->dev, "biu");
+ host->biu_clk = devm_clk_get(host->dev, "biu");
if (IS_ERR(host->biu_clk)) {
dev_dbg(host->dev, "biu clock not available\n");
} else {
ret = clk_prepare_enable(host->biu_clk);
if (ret) {
dev_err(host->dev, "failed to enable biu clock\n");
- clk_put(host->biu_clk);
return ret;
}
}
- host->ciu_clk = clk_get(host->dev, "ciu");
+ host->ciu_clk = devm_clk_get(host->dev, "ciu");
if (IS_ERR(host->ciu_clk)) {
dev_dbg(host->dev, "ciu clock not available\n");
} else {
ret = clk_prepare_enable(host->ciu_clk);
if (ret) {
dev_err(host->dev, "failed to enable ciu clock\n");
- clk_put(host->ciu_clk);
goto err_clk_biu;
}
}
@@ -2224,7 +2228,8 @@ int dw_mci_probe(struct dw_mci *host)
if (!host->card_workqueue)
goto err_dmaunmap;
INIT_WORK(&host->card_work, dw_mci_work_routine_card);
- ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
+ ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
+ host->irq_flags, "dw-mci", host);
if (ret)
goto err_workqueue;
@@ -2262,7 +2267,7 @@ int dw_mci_probe(struct dw_mci *host)
} else {
dev_dbg(host->dev, "attempted to initialize %d slots, "
"but failed on all\n", host->num_slots);
- goto err_init_slot;
+ goto err_workqueue;
}
/*
@@ -2282,33 +2287,24 @@ int dw_mci_probe(struct dw_mci *host)
return 0;
-err_init_slot:
- free_irq(host->irq, host);
-
err_workqueue:
destroy_workqueue(host->card_workqueue);
err_dmaunmap:
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
- dma_free_coherent(host->dev, PAGE_SIZE,
- host->sg_cpu, host->sg_dma);
- if (host->vmmc) {
+ if (host->vmmc)
regulator_disable(host->vmmc);
- regulator_put(host->vmmc);
- }
err_clk_ciu:
- if (!IS_ERR(host->ciu_clk)) {
+ if (!IS_ERR(host->ciu_clk))
clk_disable_unprepare(host->ciu_clk);
- clk_put(host->ciu_clk);
- }
+
err_clk_biu:
- if (!IS_ERR(host->biu_clk)) {
+ if (!IS_ERR(host->biu_clk))
clk_disable_unprepare(host->biu_clk);
- clk_put(host->biu_clk);
- }
+
return ret;
}
EXPORT_SYMBOL(dw_mci_probe);
@@ -2330,24 +2326,19 @@ void dw_mci_remove(struct dw_mci *host)
mci_writel(host, CLKENA, 0);
mci_writel(host, CLKSRC, 0);
- free_irq(host->irq, host);
destroy_workqueue(host->card_workqueue);
- dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
- if (host->vmmc) {
+ if (host->vmmc)
regulator_disable(host->vmmc);
- regulator_put(host->vmmc);
- }
if (!IS_ERR(host->ciu_clk))
clk_disable_unprepare(host->ciu_clk);
+
if (!IS_ERR(host->biu_clk))
clk_disable_unprepare(host->biu_clk);
- clk_put(host->ciu_clk);
- clk_put(host->biu_clk);
}
EXPORT_SYMBOL(dw_mci_remove);
@@ -2411,6 +2402,11 @@ int dw_mci_resume(struct dw_mci *host)
struct dw_mci_slot *slot = host->slot[i];
if (!slot)
continue;
+ if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+ dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+ dw_mci_setup_bus(slot, true);
+ }
+
ret = mmc_resume_host(host->slot[i]->mmc);
if (ret < 0)
return ret;
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
index c8852a8128a9..2391c6b7a4bb 100644
--- a/drivers/mmc/host/jz4740_mmc.c
+++ b/drivers/mmc/host/jz4740_mmc.c
@@ -702,7 +702,7 @@ static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = {
JZ_GPIO_BULK_PIN(MSC_DATA3),
};
-static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
+static int jz4740_mmc_request_gpio(struct device *dev, int gpio,
const char *name, bool output, int value)
{
int ret;
@@ -724,7 +724,7 @@ static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio,
return 0;
}
-static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev)
+static int jz4740_mmc_request_gpios(struct platform_device *pdev)
{
int ret;
struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
@@ -759,7 +759,7 @@ err:
return ret;
}
-static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev,
+static int jz4740_mmc_request_cd_irq(struct platform_device *pdev,
struct jz4740_mmc_host *host)
{
struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data;
@@ -802,7 +802,7 @@ static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host)
return num_pins;
}
-static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
+static int jz4740_mmc_probe(struct platform_device* pdev)
{
int ret;
struct mmc_host *mmc;
@@ -938,7 +938,7 @@ err_free_host:
return ret;
}
-static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
+static int jz4740_mmc_remove(struct platform_device *pdev)
{
struct jz4740_mmc_host *host = platform_get_drvdata(pdev);
@@ -1004,7 +1004,7 @@ const struct dev_pm_ops jz4740_mmc_pm_ops = {
static struct platform_driver jz4740_mmc_driver = {
.probe = jz4740_mmc_probe,
- .remove = __devexit_p(jz4740_mmc_remove),
+ .remove = jz4740_mmc_remove,
.driver = {
.name = "jz4740-mmc",
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index a600eabbd6c3..74145d1d51f5 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1485,7 +1485,7 @@ nomem:
}
-static int __devexit mmc_spi_remove(struct spi_device *spi)
+static int mmc_spi_remove(struct spi_device *spi)
{
struct mmc_host *mmc = dev_get_drvdata(&spi->dev);
struct mmc_spi_host *host;
@@ -1517,7 +1517,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
return 0;
}
-static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
+static struct of_device_id mmc_spi_of_match_table[] = {
{ .compatible = "mmc-spi-slot", },
{},
};
@@ -1529,7 +1529,7 @@ static struct spi_driver mmc_spi_driver = {
.of_match_table = mmc_spi_of_match_table,
},
.probe = mmc_spi_probe,
- .remove = __devexit_p(mmc_spi_remove),
+ .remove = mmc_spi_remove,
};
module_spi_driver(mmc_spi_driver);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index edc3e9baf0e7..ec28d175d9c8 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -261,7 +261,7 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
* no custom DMA interfaces are supported.
*/
#ifdef CONFIG_DMA_ENGINE
-static void __devinit mmci_dma_setup(struct mmci_host *host)
+static void mmci_dma_setup(struct mmci_host *host)
{
struct mmci_platform_data *plat = host->plat;
const char *rxname, *txname;
@@ -337,7 +337,7 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
}
/*
- * This is used in __devinit or __devexit so inline it
+ * This is used in or so inline it
* so it can be discarded.
*/
static inline void mmci_dma_release(struct mmci_host *host)
@@ -1255,7 +1255,7 @@ static void mmci_dt_populate_generic_pdata(struct device_node *np,
}
#endif
-static int __devinit mmci_probe(struct amba_device *dev,
+static int mmci_probe(struct amba_device *dev,
const struct amba_id *id)
{
struct mmci_platform_data *plat = dev->dev.platform_data;
@@ -1522,7 +1522,7 @@ static int __devinit mmci_probe(struct amba_device *dev,
return ret;
}
-static int __devexit mmci_remove(struct amba_device *dev)
+static int mmci_remove(struct amba_device *dev)
{
struct mmc_host *mmc = amba_get_drvdata(dev);
@@ -1669,7 +1669,7 @@ static struct amba_driver mmci_driver = {
.pm = &mmci_dev_pm_ops,
},
.probe = mmci_probe,
- .remove = __devexit_p(mmci_remove),
+ .remove = mmci_remove,
.id_table = mmci_ids,
};
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 6290b7f1ccfe..29e680f193a0 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -240,7 +240,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
return 0;
for_each_sg(data->sg, sg, data->sg_len, i) {
- if (sg->offset & 3 || sg->length & 3) {
+ if (sg->offset & 3 || sg->length & 3 || sg->length < 512) {
host->do_dma = 0;
return 0;
}
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 80d1e6d4b0ae..206fe499ded5 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -43,7 +43,6 @@
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
-#include <linux/mmc/mxs-mmc.h>
#include <linux/spi/mxs-spi.h>
#define DRIVER_NAME "mxs-mmc"
@@ -593,13 +592,13 @@ static int mxs_mmc_probe(struct platform_device *pdev)
struct mxs_mmc_host *host;
struct mmc_host *mmc;
struct resource *iores, *dmares;
- struct mxs_mmc_platform_data *pdata;
struct pinctrl *pinctrl;
int ret = 0, irq_err, irq_dma;
dma_cap_mask_t mask;
struct regulator *reg_vmmc;
enum of_gpio_flags flags;
struct mxs_ssp *ssp;
+ u32 bus_width = 0;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -682,25 +681,15 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
- pdata = mmc_dev(host->mmc)->platform_data;
- if (!pdata) {
- u32 bus_width = 0;
- of_property_read_u32(np, "bus-width", &bus_width);
- if (bus_width == 4)
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- else if (bus_width == 8)
- mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
- host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0,
- &flags);
- if (flags & OF_GPIO_ACTIVE_LOW)
- host->wp_inverted = 1;
- } else {
- if (pdata->flags & SLOTF_8_BIT_CAPABLE)
- mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
- if (pdata->flags & SLOTF_4_BIT_CAPABLE)
- mmc->caps |= MMC_CAP_4_BIT_DATA;
- host->wp_gpio = pdata->wp_gpio;
- }
+ of_property_read_u32(np, "bus-width", &bus_width);
+ if (bus_width == 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+ else if (bus_width == 8)
+ mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+ host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags);
+
+ if (flags & OF_GPIO_ACTIVE_LOW)
+ host->wp_inverted = 1;
mmc->f_min = 400000;
mmc->f_max = 288000000;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 48ad361613ef..4e749ab690c8 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1214,7 +1214,7 @@ static const struct mmc_host_ops mmc_omap_ops = {
.set_ios = mmc_omap_set_ios,
};
-static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
{
struct mmc_omap_slot *slot = NULL;
struct mmc_host *mmc;
@@ -1309,7 +1309,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
mmc_free_host(mmc);
}
-static int __devinit mmc_omap_probe(struct platform_device *pdev)
+static int mmc_omap_probe(struct platform_device *pdev)
{
struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
struct mmc_omap_host *host = NULL;
@@ -1478,7 +1478,7 @@ err_free_mem_region:
return ret;
}
-static int __devexit mmc_omap_remove(struct platform_device *pdev)
+static int mmc_omap_remove(struct platform_device *pdev)
{
struct mmc_omap_host *host = platform_get_drvdata(pdev);
int i;
@@ -1566,7 +1566,7 @@ static int mmc_omap_resume(struct platform_device *pdev)
static struct platform_driver mmc_omap_driver = {
.probe = mmc_omap_probe,
- .remove = __devexit_p(mmc_omap_remove),
+ .remove = mmc_omap_remove,
.suspend = mmc_omap_suspend,
.resume = mmc_omap_resume,
.driver = {
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index fedd258cc4ea..e1f3c1135f93 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -37,6 +37,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <mach/hardware.h>
#include <plat/mmc.h>
@@ -62,6 +63,7 @@
#define VS18 (1 << 26)
#define VS30 (1 << 25)
+#define HSS (1 << 21)
#define SDVS18 (0x5 << 9)
#define SDVS30 (0x6 << 9)
#define SDVS33 (0x7 << 9)
@@ -78,28 +80,17 @@
#define CLKD_SHIFT 6
#define DTO_MASK 0x000F0000
#define DTO_SHIFT 16
-#define INT_EN_MASK 0x307F0033
-#define BWR_ENABLE (1 << 4)
-#define BRR_ENABLE (1 << 5)
-#define DTO_ENABLE (1 << 20)
#define INIT_STREAM (1 << 1)
#define DP_SELECT (1 << 21)
#define DDIR (1 << 4)
-#define DMA_EN 0x1
+#define DMAE 0x1
#define MSBS (1 << 5)
#define BCE (1 << 1)
#define FOUR_BIT (1 << 1)
+#define HSPE (1 << 2)
#define DDR (1 << 19)
#define DW8 (1 << 5)
-#define CC 0x1
-#define TC 0x02
#define OD 0x1
-#define ERR (1 << 15)
-#define CMD_TIMEOUT (1 << 16)
-#define DATA_TIMEOUT (1 << 20)
-#define CMD_CRC (1 << 17)
-#define DATA_CRC (1 << 21)
-#define CARD_ERR (1 << 28)
#define STAT_CLEAR 0xFFFFFFFF
#define INIT_STREAM_CMD 0x00000000
#define DUAL_VOLT_OCR_BIT 7
@@ -108,6 +99,26 @@
#define SOFTRESET (1 << 1)
#define RESETDONE (1 << 0)
+/* Interrupt masks for IE and ISE register */
+#define CC_EN (1 << 0)
+#define TC_EN (1 << 1)
+#define BWR_EN (1 << 4)
+#define BRR_EN (1 << 5)
+#define ERR_EN (1 << 15)
+#define CTO_EN (1 << 16)
+#define CCRC_EN (1 << 17)
+#define CEB_EN (1 << 18)
+#define CIE_EN (1 << 19)
+#define DTO_EN (1 << 20)
+#define DCRC_EN (1 << 21)
+#define DEB_EN (1 << 22)
+#define CERR_EN (1 << 28)
+#define BADA_EN (1 << 29)
+
+#define INT_EN_MASK (BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\
+ DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
+ BRR_EN | BWR_EN | TC_EN | CC_EN)
+
#define MMC_AUTOSUSPEND_DELAY 100
#define MMC_TIMEOUT_MS 20
#define OMAP_MMC_MIN_CLOCK 400000
@@ -302,7 +313,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
reg = regulator_get(host->dev, "vmmc");
if (IS_ERR(reg)) {
- dev_dbg(host->dev, "vmmc regulator missing\n");
+ dev_err(host->dev, "vmmc regulator missing\n");
return PTR_ERR(reg);
} else {
mmc_slot(host).set_power = omap_hsmmc_set_power;
@@ -455,13 +466,13 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
unsigned int irq_mask;
if (host->use_dma)
- irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
+ irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
else
irq_mask = INT_EN_MASK;
/* Disable timeout for erases */
if (cmd->opcode == MMC_ERASE)
- irq_mask &= ~DTO_ENABLE;
+ irq_mask &= ~DTO_EN;
OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
@@ -494,6 +505,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
struct mmc_ios *ios = &host->mmc->ios;
unsigned long regval;
unsigned long timeout;
+ unsigned long clkdiv;
dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
@@ -501,7 +513,8 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
regval = OMAP_HSMMC_READ(host->base, SYSCTL);
regval = regval & ~(CLKD_MASK | DTO_MASK);
- regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
+ clkdiv = calc_divisor(host, ios);
+ regval = regval | (clkdiv << 6) | (DTO << 16);
OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
OMAP_HSMMC_WRITE(host->base, SYSCTL,
OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
@@ -512,6 +525,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
&& time_before(jiffies, timeout))
cpu_relax();
+ /*
+ * Enable High-Speed Support
+ * Pre-Requisites
+ * - Controller should support High-Speed-Enable Bit
+ * - Controller should not be using DDR Mode
+ * - Controller should advertise that it supports High Speed
+ * in capabilities register
+ * - MMC/SD clock coming out of controller > 25MHz
+ */
+ if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
+ (ios->timing != MMC_TIMING_UHS_DDR50) &&
+ ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
+ regval = OMAP_HSMMC_READ(host->base, HCTL);
+ if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
+ regval |= HSPE;
+ else
+ regval &= ~HSPE;
+
+ OMAP_HSMMC_WRITE(host->base, HCTL, regval);
+ }
+
omap_hsmmc_start_clock(host);
}
@@ -676,8 +710,8 @@ static void send_init_stream(struct omap_hsmmc_host *host)
OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
- while ((reg != CC) && time_before(jiffies, timeout))
- reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
+ while ((reg != CC_EN) && time_before(jiffies, timeout))
+ reg = OMAP_HSMMC_READ(host->base, STAT) & CC_EN;
OMAP_HSMMC_WRITE(host->base, CON,
OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
@@ -768,7 +802,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
}
if (host->use_dma)
- cmdreg |= DMA_EN;
+ cmdreg |= DMAE;
host->req_in_progress = 1;
@@ -968,16 +1002,20 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
__func__);
}
-static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err)
+static void hsmmc_command_incomplete(struct omap_hsmmc_host *host,
+ int err, int end_cmd)
{
- omap_hsmmc_reset_controller_fsm(host, SRC);
- host->cmd->error = err;
+ if (end_cmd) {
+ omap_hsmmc_reset_controller_fsm(host, SRC);
+ if (host->cmd)
+ host->cmd->error = err;
+ }
if (host->data) {
omap_hsmmc_reset_controller_fsm(host, SRD);
omap_hsmmc_dma_cleanup(host, err);
- }
-
+ } else if (host->mrq && host->mrq->cmd)
+ host->mrq->cmd->error = err;
}
static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
@@ -988,23 +1026,25 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
data = host->data;
dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
- if (status & ERR) {
+ if (status & ERR_EN) {
omap_hsmmc_dbg_report_irq(host, status);
- if (status & (CMD_TIMEOUT | DATA_TIMEOUT))
- hsmmc_command_incomplete(host, -ETIMEDOUT);
- else if (status & (CMD_CRC | DATA_CRC))
- hsmmc_command_incomplete(host, -EILSEQ);
- end_cmd = 1;
+ if (status & (CTO_EN | CCRC_EN))
+ end_cmd = 1;
+ if (status & (CTO_EN | DTO_EN))
+ hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd);
+ else if (status & (CCRC_EN | DCRC_EN))
+ hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
+
if (host->data || host->response_busy) {
- end_trans = 1;
+ end_trans = !end_cmd;
host->response_busy = 0;
}
}
- if (end_cmd || ((status & CC) && host->cmd))
+ if (end_cmd || ((status & CC_EN) && host->cmd))
omap_hsmmc_cmd_done(host, host->cmd);
- if ((end_trans || (status & TC)) && host->mrq)
+ if ((end_trans || (status & TC_EN)) && host->mrq)
omap_hsmmc_xfer_done(host, data);
}
@@ -1101,7 +1141,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
return 0;
err:
- dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
+ dev_err(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
return ret;
}
@@ -1360,7 +1400,7 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
if (host->use_dma) {
ret = omap_hsmmc_start_dma_transfer(host, req);
if (ret != 0) {
- dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
+ dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
return ret;
}
}
@@ -1678,7 +1718,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
{
struct omap_mmc_platform_data *pdata;
struct device_node *np = dev->of_node;
- u32 bus_width;
+ u32 bus_width, max_freq;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -1705,6 +1745,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
if (of_find_property(np, "ti,needs-special-reset", NULL))
pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+ if (!of_property_read_u32(np, "max-frequency", &max_freq))
+ pdata->max_freq = max_freq;
+
+ if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
+ pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
+
return pdata;
}
#else
@@ -1715,7 +1761,7 @@ static inline struct omap_mmc_platform_data
}
#endif
-static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+static int omap_hsmmc_probe(struct platform_device *pdev)
{
struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
struct mmc_host *mmc;
@@ -1725,6 +1771,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
const struct of_device_id *match;
dma_cap_mask_t mask;
unsigned tx_req, rx_req;
+ struct pinctrl *pinctrl;
match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
if (match) {
@@ -1821,7 +1868,6 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
* MMC can still work without debounce clock.
*/
if (IS_ERR(host->dbclk)) {
- dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");
host->dbclk = NULL;
} else if (clk_prepare_enable(host->dbclk) != 0) {
dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
@@ -1889,13 +1935,13 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
ret = request_irq(host->irq, omap_hsmmc_irq, 0,
mmc_hostname(mmc), host);
if (ret) {
- dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
+ dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
goto err_irq;
}
if (pdata->init != NULL) {
if (pdata->init(&pdev->dev) != 0) {
- dev_dbg(mmc_dev(host->mmc),
+ dev_err(mmc_dev(host->mmc),
"Unable to configure MMC IRQs\n");
goto err_irq_cd_init;
}
@@ -1918,7 +1964,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
mmc_hostname(mmc), host);
if (ret) {
- dev_dbg(mmc_dev(host->mmc),
+ dev_err(mmc_dev(host->mmc),
"Unable to grab MMC CD IRQ\n");
goto err_irq_cd;
}
@@ -1928,6 +1974,11 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
omap_hsmmc_disable_irq(host);
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev,
+ "pins are not configured from the driver\n");
+
omap_hsmmc_protect_card(host);
mmc_add_host(mmc);
@@ -1986,7 +2037,7 @@ err:
return ret;
}
-static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
+static int omap_hsmmc_remove(struct platform_device *pdev)
{
struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
struct resource *res;
@@ -2027,6 +2078,25 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM
+static int omap_hsmmc_prepare(struct device *dev)
+{
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+ if (host->pdata->suspend)
+ return host->pdata->suspend(dev, host->slot_id);
+
+ return 0;
+}
+
+static void omap_hsmmc_complete(struct device *dev)
+{
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+ if (host->pdata->resume)
+ host->pdata->resume(dev, host->slot_id);
+
+}
+
static int omap_hsmmc_suspend(struct device *dev)
{
int ret = 0;
@@ -2040,23 +2110,10 @@ static int omap_hsmmc_suspend(struct device *dev)
pm_runtime_get_sync(host->dev);
host->suspended = 1;
- if (host->pdata->suspend) {
- ret = host->pdata->suspend(dev, host->slot_id);
- if (ret) {
- dev_dbg(dev, "Unable to handle MMC board"
- " level suspend\n");
- host->suspended = 0;
- return ret;
- }
- }
ret = mmc_suspend_host(host->mmc);
if (ret) {
host->suspended = 0;
- if (host->pdata->resume) {
- if (host->pdata->resume(dev, host->slot_id))
- dev_dbg(dev, "Unmask interrupt failed\n");
- }
goto err;
}
@@ -2093,12 +2150,6 @@ static int omap_hsmmc_resume(struct device *dev)
if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
omap_hsmmc_conf_bus_power(host);
- if (host->pdata->resume) {
- ret = host->pdata->resume(dev, host->slot_id);
- if (ret)
- dev_dbg(dev, "Unmask interrupt failed\n");
- }
-
omap_hsmmc_protect_card(host);
/* Notify the core to resume the host */
@@ -2114,8 +2165,10 @@ static int omap_hsmmc_resume(struct device *dev)
}
#else
+#define omap_hsmmc_prepare NULL
+#define omap_hsmmc_complete NULL
#define omap_hsmmc_suspend NULL
-#define omap_hsmmc_resume NULL
+#define omap_hsmmc_resume NULL
#endif
static int omap_hsmmc_runtime_suspend(struct device *dev)
@@ -2143,13 +2196,15 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
.suspend = omap_hsmmc_suspend,
.resume = omap_hsmmc_resume,
+ .prepare = omap_hsmmc_prepare,
+ .complete = omap_hsmmc_complete,
.runtime_suspend = omap_hsmmc_runtime_suspend,
.runtime_resume = omap_hsmmc_runtime_resume,
};
static struct platform_driver omap_hsmmc_driver = {
.probe = omap_hsmmc_probe,
- .remove = __devexit_p(omap_hsmmc_remove),
+ .remove = omap_hsmmc_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 3f9d6d577a91..2b2f65ada22e 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -584,7 +584,7 @@ static const struct of_device_id pxa_mmc_dt_ids[] = {
MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
-static int __devinit pxamci_of_init(struct platform_device *pdev)
+static int pxamci_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct pxamci_platform_data *pdata;
@@ -614,7 +614,7 @@ static int __devinit pxamci_of_init(struct platform_device *pdev)
return 0;
}
#else
-static int __devinit pxamci_of_init(struct platform_device *pdev)
+static int pxamci_of_init(struct platform_device *pdev)
{
return 0;
}
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
new file mode 100644
index 000000000000..12eff6f8cab7
--- /dev/null
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -0,0 +1,1348 @@
+/* Realtek PCI-Express SD/MMC Card Interface driver
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/card.h>
+#include <linux/mfd/rtsx_pci.h>
+#include <asm/unaligned.h>
+
+/* SD Tuning Data Structure
+ * Record continuous timing phase path
+ */
+struct timing_phase_path {
+ int start;
+ int end;
+ int mid;
+ int len;
+};
+
+struct realtek_pci_sdmmc {
+ struct platform_device *pdev;
+ struct rtsx_pcr *pcr;
+ struct mmc_host *mmc;
+ struct mmc_request *mrq;
+
+ struct mutex host_mutex;
+
+ u8 ssc_depth;
+ unsigned int clock;
+ bool vpclk;
+ bool double_clk;
+ bool eject;
+ bool initial_mode;
+ bool ddr_mode;
+};
+
+static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
+{
+ return &(host->pdev->dev);
+}
+
+static inline void sd_clear_error(struct realtek_pci_sdmmc *host)
+{
+ rtsx_pci_write_register(host->pcr, CARD_STOP,
+ SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+}
+
+#ifdef DEBUG
+static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ u16 i;
+ u8 *ptr;
+
+ /* Print SD host internal registers */
+ rtsx_pci_init_cmd(pcr);
+ for (i = 0xFDA0; i <= 0xFDAE; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+ for (i = 0xFD52; i <= 0xFD69; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, i, 0, 0);
+ rtsx_pci_send_cmd(pcr, 100);
+
+ ptr = rtsx_pci_get_cmd_data(pcr);
+ for (i = 0xFDA0; i <= 0xFDAE; i++)
+ dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+ for (i = 0xFD52; i <= 0xFD69; i++)
+ dev_dbg(sdmmc_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+}
+#else
+#define sd_print_debug_regs(host)
+#endif /* DEBUG */
+
+static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+ u8 *buf, int buf_len, int timeout)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err, i;
+ u8 trans_mode;
+
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__, cmd[0] - 0x40);
+
+ if (!buf)
+ buf_len = 0;
+
+ if ((cmd[0] & 0x3F) == MMC_SEND_TUNING_BLOCK)
+ trans_mode = SD_TM_AUTO_TUNING;
+ else
+ trans_mode = SD_TM_NORMAL_READ;
+
+ rtsx_pci_init_cmd(pcr);
+
+ for (i = 0; i < 5; i++)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0 + i, 0xFF, cmd[i]);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+ 0xFF, (u8)(byte_cnt >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+ if (trans_mode != SD_TM_AUTO_TUNING)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+ 0xFF, trans_mode | SD_TRANSFER_START);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ err = rtsx_pci_send_cmd(pcr, timeout);
+ if (err < 0) {
+ sd_print_debug_regs(host);
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_pci_send_cmd fail (err = %d)\n", err);
+ return err;
+ }
+
+ if (buf && buf_len) {
+ err = rtsx_pci_read_ppbuf(pcr, buf, buf_len);
+ if (err < 0) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_pci_read_ppbuf fail (err = %d)\n", err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
+ u8 *buf, int buf_len, int timeout)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err, i;
+ u8 trans_mode;
+
+ if (!buf)
+ buf_len = 0;
+
+ if (buf && buf_len) {
+ err = rtsx_pci_write_ppbuf(pcr, buf, buf_len);
+ if (err < 0) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_pci_write_ppbuf fail (err = %d)\n", err);
+ return err;
+ }
+ }
+
+ trans_mode = cmd ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3;
+ rtsx_pci_init_cmd(pcr);
+
+ if (cmd) {
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d\n", __func__,
+ cmd[0] - 0x40);
+
+ for (i = 0; i < 5; i++)
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ SD_CMD0 + i, 0xFF, cmd[i]);
+ }
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+ 0xFF, (u8)(byte_cnt >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+ trans_mode | SD_TRANSFER_START);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ err = rtsx_pci_send_cmd(pcr, timeout);
+ if (err < 0) {
+ sd_print_debug_regs(host);
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_pci_send_cmd fail (err = %d)\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
+ struct mmc_command *cmd)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ u8 cmd_idx = (u8)cmd->opcode;
+ u32 arg = cmd->arg;
+ int err = 0;
+ int timeout = 100;
+ int i;
+ u8 *ptr;
+ int stat_idx = 0;
+ u8 rsp_type;
+ int rsp_len = 5;
+
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
+ __func__, cmd_idx, arg);
+
+ /* Response type:
+ * R0
+ * R1, R5, R6, R7
+ * R1b
+ * R2
+ * R3, R4
+ */
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE:
+ rsp_type = SD_RSP_TYPE_R0;
+ rsp_len = 0;
+ break;
+ case MMC_RSP_R1:
+ rsp_type = SD_RSP_TYPE_R1;
+ break;
+ case MMC_RSP_R1B:
+ rsp_type = SD_RSP_TYPE_R1b;
+ break;
+ case MMC_RSP_R2:
+ rsp_type = SD_RSP_TYPE_R2;
+ rsp_len = 16;
+ break;
+ case MMC_RSP_R3:
+ rsp_type = SD_RSP_TYPE_R3;
+ break;
+ default:
+ dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R1b)
+ timeout = 3000;
+
+ if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+ err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+ 0xFF, SD_CLK_TOGGLE_EN);
+ if (err < 0)
+ goto out;
+ }
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER,
+ 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END | SD_STAT_IDLE,
+ SD_TRANSFER_END | SD_STAT_IDLE);
+
+ if (rsp_type == SD_RSP_TYPE_R2) {
+ /* Read data from ping-pong buffer */
+ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+ stat_idx = 16;
+ } else if (rsp_type != SD_RSP_TYPE_R0) {
+ /* Read data from SD_CMDx registers */
+ for (i = SD_CMD0; i <= SD_CMD4; i++)
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+ stat_idx = 5;
+ }
+
+ rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
+
+ err = rtsx_pci_send_cmd(pcr, timeout);
+ if (err < 0) {
+ sd_print_debug_regs(host);
+ sd_clear_error(host);
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_pci_send_cmd error (err = %d)\n", err);
+ goto out;
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R0) {
+ err = 0;
+ goto out;
+ }
+
+ /* Eliminate returned value of CHECK_REG_CMD */
+ ptr = rtsx_pci_get_cmd_data(pcr) + 1;
+
+ /* Check (Start,Transmission) bit of Response */
+ if ((ptr[0] & 0xC0) != 0) {
+ err = -EILSEQ;
+ dev_dbg(sdmmc_dev(host), "Invalid response bit\n");
+ goto out;
+ }
+
+ /* Check CRC7 */
+ if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+ if (ptr[stat_idx] & SD_CRC7_ERR) {
+ err = -EILSEQ;
+ dev_dbg(sdmmc_dev(host), "CRC7 error\n");
+ goto out;
+ }
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R2) {
+ for (i = 0; i < 4; i++) {
+ cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n",
+ i, cmd->resp[i]);
+ }
+ } else {
+ cmd->resp[0] = get_unaligned_be32(ptr + 1);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+ cmd->resp[0]);
+ }
+
+out:
+ cmd->error = err;
+}
+
+static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ struct mmc_host *mmc = host->mmc;
+ struct mmc_card *card = mmc->card;
+ struct mmc_data *data = mrq->data;
+ int uhs = mmc_sd_card_uhs(card);
+ int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
+ u8 cfg2, trans_mode;
+ int err;
+ size_t data_len = data->blksz * data->blocks;
+
+ if (read) {
+ cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
+ trans_mode = SD_TM_AUTO_READ_3;
+ } else {
+ cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+ trans_mode = SD_TM_AUTO_WRITE_3;
+ }
+
+ if (!uhs)
+ cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L,
+ 0xFF, (u8)data->blocks);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H,
+ 0xFF, (u8)(data->blocks >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+ DMA_DONE_INT, DMA_DONE_INT);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3,
+ 0xFF, (u8)(data_len >> 24));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2,
+ 0xFF, (u8)(data_len >> 16));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1,
+ 0xFF, (u8)(data_len >> 8));
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len);
+ if (read) {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+ 0x03 | DMA_PACK_SIZE_MASK,
+ DMA_DIR_FROM_CARD | DMA_EN | DMA_512);
+ } else {
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL,
+ 0x03 | DMA_PACK_SIZE_MASK,
+ DMA_DIR_TO_CARD | DMA_EN | DMA_512);
+ }
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, RING_BUFFER);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+ trans_mode | SD_TRANSFER_START);
+ rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ rtsx_pci_send_cmd_no_wait(pcr);
+
+ err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
+ if (err < 0) {
+ sd_clear_error(host);
+ return err;
+ }
+
+ return 0;
+}
+
+static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+ rtsx_pci_write_register(host->pcr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+ rtsx_pci_write_register(host->pcr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
+static void sd_normal_rw(struct realtek_pci_sdmmc *host,
+ struct mmc_request *mrq)
+{
+ struct mmc_command *cmd = mrq->cmd;
+ struct mmc_data *data = mrq->data;
+ u8 _cmd[5], *buf;
+
+ _cmd[0] = 0x40 | (u8)cmd->opcode;
+ put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1]));
+
+ buf = kzalloc(data->blksz, GFP_NOIO);
+ if (!buf) {
+ cmd->error = -ENOMEM;
+ return;
+ }
+
+ if (data->flags & MMC_DATA_READ) {
+ if (host->initial_mode)
+ sd_disable_initial_mode(host);
+
+ cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf,
+ data->blksz, 200);
+
+ if (host->initial_mode)
+ sd_enable_initial_mode(host);
+
+ sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz);
+ } else {
+ sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz);
+
+ cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf,
+ data->blksz, 200);
+ }
+
+ kfree(buf);
+}
+
+static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n",
+ __func__, sample_point);
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, PHASE_NOT_RESET);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static u8 sd_search_final_phase(struct realtek_pci_sdmmc *host, u32 phase_map)
+{
+ struct timing_phase_path path[MAX_PHASE + 1];
+ int i, j, cont_path_cnt;
+ int new_block, max_len, final_path_idx;
+ u8 final_phase = 0xFF;
+
+ /* Parse phase_map, take it as a bit-ring */
+ cont_path_cnt = 0;
+ new_block = 1;
+ j = 0;
+ for (i = 0; i < MAX_PHASE + 1; i++) {
+ if (phase_map & (1 << i)) {
+ if (new_block) {
+ new_block = 0;
+ j = cont_path_cnt++;
+ path[j].start = i;
+ path[j].end = i;
+ } else {
+ path[j].end = i;
+ }
+ } else {
+ new_block = 1;
+ if (cont_path_cnt) {
+ /* Calculate path length and middle point */
+ int idx = cont_path_cnt - 1;
+ path[idx].len =
+ path[idx].end - path[idx].start + 1;
+ path[idx].mid =
+ path[idx].start + path[idx].len / 2;
+ }
+ }
+ }
+
+ if (cont_path_cnt == 0) {
+ dev_dbg(sdmmc_dev(host), "No continuous phase path\n");
+ goto finish;
+ } else {
+ /* Calculate last continuous path length and middle point */
+ int idx = cont_path_cnt - 1;
+ path[idx].len = path[idx].end - path[idx].start + 1;
+ path[idx].mid = path[idx].start + path[idx].len / 2;
+ }
+
+ /* Connect the first and last continuous paths if they are adjacent */
+ if (!path[0].start && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
+ /* Using negative index */
+ path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
+ path[0].len += path[cont_path_cnt - 1].len;
+ path[0].mid = path[0].start + path[0].len / 2;
+ /* Convert negative middle point index to positive one */
+ if (path[0].mid < 0)
+ path[0].mid += MAX_PHASE + 1;
+ cont_path_cnt--;
+ }
+
+ /* Choose the longest continuous phase path */
+ max_len = 0;
+ final_phase = 0;
+ final_path_idx = 0;
+ for (i = 0; i < cont_path_cnt; i++) {
+ if (path[i].len > max_len) {
+ max_len = path[i].len;
+ final_phase = (u8)path[i].mid;
+ final_path_idx = i;
+ }
+
+ dev_dbg(sdmmc_dev(host), "path[%d].start = %d\n",
+ i, path[i].start);
+ dev_dbg(sdmmc_dev(host), "path[%d].end = %d\n",
+ i, path[i].end);
+ dev_dbg(sdmmc_dev(host), "path[%d].len = %d\n",
+ i, path[i].len);
+ dev_dbg(sdmmc_dev(host), "path[%d].mid = %d\n",
+ i, path[i].mid);
+ }
+
+finish:
+ dev_dbg(sdmmc_dev(host), "Final chosen phase: %d\n", final_phase);
+ return final_phase;
+}
+
+static void sd_wait_data_idle(struct realtek_pci_sdmmc *host)
+{
+ int err, i;
+ u8 val = 0;
+
+ for (i = 0; i < 100; i++) {
+ err = rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val);
+ if (val & SD_DATA_IDLE)
+ return;
+
+ udelay(100);
+ }
+}
+
+static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host,
+ u8 opcode, u8 sample_point)
+{
+ int err;
+ u8 cmd[5] = {0};
+
+ err = sd_change_phase(host, sample_point);
+ if (err < 0)
+ return err;
+
+ cmd[0] = 0x40 | opcode;
+ err = sd_read_data(host, cmd, 0x40, NULL, 0, 100);
+ if (err < 0) {
+ /* Wait till SD DATA IDLE */
+ sd_wait_data_idle(host);
+ sd_clear_error(host);
+ return err;
+ }
+
+ return 0;
+}
+
+static int sd_tuning_phase(struct realtek_pci_sdmmc *host,
+ u8 opcode, u32 *phase_map)
+{
+ int err, i;
+ u32 raw_phase_map = 0;
+
+ for (i = MAX_PHASE; i >= 0; i--) {
+ err = sd_tuning_rx_cmd(host, opcode, (u8)i);
+ if (err == 0)
+ raw_phase_map |= 1 << i;
+ }
+
+ if (phase_map)
+ *phase_map = raw_phase_map;
+
+ return 0;
+}
+
+static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
+{
+ int err, i;
+ u32 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map;
+ u8 final_phase;
+
+ for (i = 0; i < RX_TUNING_CNT; i++) {
+ err = sd_tuning_phase(host, opcode, &(raw_phase_map[i]));
+ if (err < 0)
+ return err;
+
+ if (raw_phase_map[i] == 0)
+ break;
+ }
+
+ phase_map = 0xFFFFFFFF;
+ for (i = 0; i < RX_TUNING_CNT; i++) {
+ dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%08x\n",
+ i, raw_phase_map[i]);
+ phase_map &= raw_phase_map[i];
+ }
+ dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%08x\n", phase_map);
+
+ if (phase_map) {
+ final_phase = sd_search_final_phase(host, phase_map);
+ if (final_phase == 0xFF)
+ return -EINVAL;
+
+ err = sd_change_phase(host, final_phase);
+ if (err < 0)
+ return err;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ struct mmc_command *cmd = mrq->cmd;
+ struct mmc_data *data = mrq->data;
+ unsigned int data_size = 0;
+
+ if (host->eject) {
+ cmd->error = -ENOMEDIUM;
+ goto finish;
+ }
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
+ host->initial_mode, host->double_clk, host->vpclk);
+ rtsx_pci_write_register(pcr, CARD_SELECT, 0x07, SD_MOD_SEL);
+ rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_48_SD);
+
+ mutex_lock(&host->host_mutex);
+ host->mrq = mrq;
+ mutex_unlock(&host->host_mutex);
+
+ if (mrq->data)
+ data_size = data->blocks * data->blksz;
+
+ if (!data_size || mmc_op_multi(cmd->opcode) ||
+ (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+ (cmd->opcode == MMC_WRITE_BLOCK)) {
+ sd_send_cmd_get_rsp(host, cmd);
+
+ if (!cmd->error && data_size) {
+ sd_rw_multi(host, mrq);
+
+ if (mmc_op_multi(cmd->opcode) && mrq->stop)
+ sd_send_cmd_get_rsp(host, mrq->stop);
+ }
+ } else {
+ sd_normal_rw(host, mrq);
+ }
+
+ if (mrq->data) {
+ if (cmd->error || data->error)
+ data->bytes_xfered = 0;
+ else
+ data->bytes_xfered = data->blocks * data->blksz;
+ }
+
+ mutex_unlock(&pcr->pcr_mutex);
+
+finish:
+ if (cmd->error)
+ dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
+
+ mutex_lock(&host->host_mutex);
+ host->mrq = NULL;
+ mutex_unlock(&host->host_mutex);
+
+ mmc_request_done(mmc, mrq);
+}
+
+static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
+ unsigned char bus_width)
+{
+ int err = 0;
+ u8 width[] = {
+ [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT,
+ [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT,
+ [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT,
+ };
+
+ if (bus_width <= MMC_BUS_WIDTH_8)
+ err = rtsx_pci_write_register(host->pcr, SD_CFG1,
+ 0x03, width[bus_width]);
+
+ return err;
+}
+
+static int sd_power_on(struct realtek_pci_sdmmc *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_48_SD);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN,
+ SD_CLK_EN, SD_CLK_EN);
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_pull_ctl_enable(pcr, RTSX_SD_CARD);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_power_on(pcr, RTSX_SD_CARD);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int sd_power_off(struct realtek_pci_sdmmc *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ rtsx_pci_init_cmd(pcr);
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0);
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+ if (err < 0)
+ return err;
+
+ err = rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+ if (err < 0)
+ return err;
+
+ return rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD);
+}
+
+static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
+ unsigned char power_mode)
+{
+ int err;
+
+ if (power_mode == MMC_POWER_OFF)
+ err = sd_power_off(host);
+ else
+ err = sd_power_on(host);
+
+ return err;
+}
+
+static int sd_set_timing(struct realtek_pci_sdmmc *host,
+ unsigned char timing, bool *ddr_mode)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err = 0;
+
+ *ddr_mode = false;
+
+ rtsx_pci_init_cmd(pcr);
+
+ switch (timing) {
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_UHS_SDR50:
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C | SD_ASYNC_FIFO_NOT_RST,
+ SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+ CLK_LOW_FREQ, CLK_LOW_FREQ);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+ break;
+
+ case MMC_TIMING_UHS_DDR50:
+ *ddr_mode = true;
+
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C | SD_ASYNC_FIFO_NOT_RST,
+ SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+ CLK_LOW_FREQ, CLK_LOW_FREQ);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+ DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
+ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
+ break;
+
+ case MMC_TIMING_MMC_HS:
+ case MMC_TIMING_SD_HS:
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C, SD_20_MODE);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+ CLK_LOW_FREQ, CLK_LOW_FREQ);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+ SD20_TX_SEL_MASK, SD20_TX_14_AHEAD);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ SD20_RX_SEL_MASK, SD20_RX_14_DELAY);
+ break;
+
+ default:
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ SD_CFG1, 0x0C, SD_20_MODE);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+ CLK_LOW_FREQ, CLK_LOW_FREQ);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+ SD_PUSH_POINT_CTL, 0xFF, 0);
+ rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ SD20_RX_SEL_MASK, SD20_RX_POS_EDGE);
+ break;
+ }
+
+ err = rtsx_pci_send_cmd(pcr, 100);
+
+ return err;
+}
+
+static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+
+ if (host->eject)
+ return;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ sd_set_bus_width(host, ios->bus_width);
+ sd_set_power_mode(host, ios->power_mode);
+ sd_set_timing(host, ios->timing, &host->ddr_mode);
+
+ host->vpclk = false;
+ host->double_clk = true;
+
+ switch (ios->timing) {
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_UHS_SDR50:
+ host->ssc_depth = RTSX_SSC_DEPTH_2M;
+ host->vpclk = true;
+ host->double_clk = false;
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_UHS_SDR25:
+ host->ssc_depth = RTSX_SSC_DEPTH_1M;
+ break;
+ default:
+ host->ssc_depth = RTSX_SSC_DEPTH_500K;
+ break;
+ }
+
+ host->initial_mode = (ios->clock <= 1000000) ? true : false;
+
+ host->clock = ios->clock;
+ rtsx_pci_switch_clock(pcr, ios->clock, host->ssc_depth,
+ host->initial_mode, host->double_clk, host->vpclk);
+
+ mutex_unlock(&pcr->pcr_mutex);
+}
+
+static int sdmmc_get_ro(struct mmc_host *mmc)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ int ro = 0;
+ u32 val;
+
+ if (host->eject)
+ return -ENOMEDIUM;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ /* Check SD mechanical write-protect switch */
+ val = rtsx_pci_readl(pcr, RTSX_BIPR);
+ dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+ if (val & SD_WRITE_PROTECT)
+ ro = 1;
+
+ mutex_unlock(&pcr->pcr_mutex);
+
+ return ro;
+}
+
+static int sdmmc_get_cd(struct mmc_host *mmc)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ int cd = 0;
+ u32 val;
+
+ if (host->eject)
+ return -ENOMEDIUM;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ /* Check SD card detect */
+ val = rtsx_pci_card_exist(pcr);
+ dev_dbg(sdmmc_dev(host), "%s: RTSX_BIPR = 0x%08x\n", __func__, val);
+ if (val & SD_EXIST)
+ cd = 1;
+
+ mutex_unlock(&pcr->pcr_mutex);
+
+ return cd;
+}
+
+static int sd_wait_voltage_stable_1(struct realtek_pci_sdmmc *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+ u8 stat;
+
+ /* Reference to Signal Voltage Switch Sequence in SD spec.
+ * Wait for a period of time so that the card can drive SD_CMD and
+ * SD_DAT[3:0] to low after sending back CMD11 response.
+ */
+ mdelay(1);
+
+ /* SD_CMD, SD_DAT[3:0] should be driven to low by card;
+ * If either one of SD_CMD,SD_DAT[3:0] is not low,
+ * abort the voltage switch sequence;
+ */
+ err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+ if (err < 0)
+ return err;
+
+ if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+ SD_DAT1_STATUS | SD_DAT0_STATUS))
+ return -EINVAL;
+
+ /* Stop toggle SD clock */
+ err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+ 0xFF, SD_CLK_FORCE_STOP);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+ u8 stat, mask, val;
+
+ /* Wait 1.8V output of voltage regulator in card stable */
+ msleep(50);
+
+ /* Toggle SD clock again */
+ err = rtsx_pci_write_register(pcr, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
+ if (err < 0)
+ return err;
+
+ /* Wait for a period of time so that the card can drive
+ * SD_DAT[3:0] to high at 1.8V
+ */
+ msleep(20);
+
+ /* SD_CMD, SD_DAT[3:0] should be pulled high by host */
+ err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat);
+ if (err < 0)
+ return err;
+
+ mask = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+ SD_DAT1_STATUS | SD_DAT0_STATUS;
+ val = SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+ SD_DAT1_STATUS | SD_DAT0_STATUS;
+ if ((stat & mask) != val) {
+ dev_dbg(sdmmc_dev(host),
+ "%s: SD_BUS_STAT = 0x%x\n", __func__, stat);
+ rtsx_pci_write_register(pcr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+ rtsx_pci_write_register(pcr, CARD_CLK_EN, 0xFF, 0);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage)
+{
+ struct rtsx_pcr *pcr = host->pcr;
+ int err;
+
+ if (voltage == SD_IO_3V3) {
+ err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+ if (err < 0)
+ return err;
+ } else if (voltage == SD_IO_1V8) {
+ err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+ if (err < 0)
+ return err;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ int err = 0;
+ u8 voltage;
+
+ dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n",
+ __func__, ios->signal_voltage);
+
+ if (host->eject)
+ return -ENOMEDIUM;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+ voltage = SD_IO_3V3;
+ else
+ voltage = SD_IO_1V8;
+
+ if (voltage == SD_IO_1V8) {
+ err = rtsx_pci_write_register(pcr,
+ SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
+ if (err < 0)
+ goto out;
+
+ err = sd_wait_voltage_stable_1(host);
+ if (err < 0)
+ goto out;
+ }
+
+ err = sd_change_bank_voltage(host, voltage);
+ if (err < 0)
+ goto out;
+
+ if (voltage == SD_IO_1V8) {
+ err = sd_wait_voltage_stable_2(host);
+ if (err < 0)
+ goto out;
+ }
+
+ /* Stop toggle SD clock in idle */
+ err = rtsx_pci_write_register(pcr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+
+out:
+ mutex_unlock(&pcr->pcr_mutex);
+
+ return err;
+}
+
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct realtek_pci_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_pcr *pcr = host->pcr;
+ int err = 0;
+
+ if (host->eject)
+ return -ENOMEDIUM;
+
+ mutex_lock(&pcr->pcr_mutex);
+
+ rtsx_pci_start_run(pcr);
+
+ if (!host->ddr_mode)
+ err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
+
+ mutex_unlock(&pcr->pcr_mutex);
+
+ return err;
+}
+
+static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
+ .request = sdmmc_request,
+ .set_ios = sdmmc_set_ios,
+ .get_ro = sdmmc_get_ro,
+ .get_cd = sdmmc_get_cd,
+ .start_signal_voltage_switch = sdmmc_switch_voltage,
+ .execute_tuning = sdmmc_execute_tuning,
+};
+
+#ifdef CONFIG_PM
+static int rtsx_pci_sdmmc_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+ struct mmc_host *mmc = host->mmc;
+ int err;
+
+ dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+ err = mmc_suspend_host(mmc);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int rtsx_pci_sdmmc_resume(struct platform_device *pdev)
+{
+ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+ struct mmc_host *mmc = host->mmc;
+
+ dev_dbg(sdmmc_dev(host), "--> %s\n", __func__);
+
+ return mmc_resume_host(mmc);
+}
+#else /* CONFIG_PM */
+#define rtsx_pci_sdmmc_suspend NULL
+#define rtsx_pci_sdmmc_resume NULL
+#endif /* CONFIG_PM */
+
+static void init_extra_caps(struct realtek_pci_sdmmc *host)
+{
+ struct mmc_host *mmc = host->mmc;
+ struct rtsx_pcr *pcr = host->pcr;
+
+ dev_dbg(sdmmc_dev(host), "pcr->extra_caps = 0x%x\n", pcr->extra_caps);
+
+ if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50)
+ mmc->caps |= MMC_CAP_UHS_SDR50;
+ if (pcr->extra_caps & EXTRA_CAPS_SD_SDR104)
+ mmc->caps |= MMC_CAP_UHS_SDR104;
+ if (pcr->extra_caps & EXTRA_CAPS_SD_DDR50)
+ mmc->caps |= MMC_CAP_UHS_DDR50;
+ if (pcr->extra_caps & EXTRA_CAPS_MMC_HSDDR)
+ mmc->caps |= MMC_CAP_1_8V_DDR;
+ if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT)
+ mmc->caps |= MMC_CAP_8_BIT_DATA;
+}
+
+static void realtek_init_host(struct realtek_pci_sdmmc *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ mmc->f_min = 250000;
+ mmc->f_max = 208000000;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST |
+ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
+ mmc->max_current_330 = 400;
+ mmc->max_current_180 = 800;
+ mmc->ops = &realtek_pci_sdmmc_ops;
+
+ init_extra_caps(host);
+
+ mmc->max_segs = 256;
+ mmc->max_seg_size = 65536;
+ mmc->max_blk_size = 512;
+ mmc->max_blk_count = 65535;
+ mmc->max_req_size = 524288;
+}
+
+static void rtsx_pci_sdmmc_card_event(struct platform_device *pdev)
+{
+ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+
+ mmc_detect_change(host->mmc, 0);
+}
+
+static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct realtek_pci_sdmmc *host;
+ struct rtsx_pcr *pcr;
+ struct pcr_handle *handle = pdev->dev.platform_data;
+
+ if (!handle)
+ return -ENXIO;
+
+ pcr = handle->pcr;
+ if (!pcr)
+ return -ENXIO;
+
+ dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller found\n");
+
+ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
+ if (!mmc)
+ return -ENOMEM;
+
+ host = mmc_priv(mmc);
+ host->pcr = pcr;
+ host->mmc = mmc;
+ host->pdev = pdev;
+ platform_set_drvdata(pdev, host);
+ pcr->slots[RTSX_SD_CARD].p_dev = pdev;
+ pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
+
+ mutex_init(&host->host_mutex);
+
+ realtek_init_host(host);
+
+ mmc_add_host(mmc);
+
+ return 0;
+}
+
+static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
+{
+ struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
+ struct rtsx_pcr *pcr;
+ struct mmc_host *mmc;
+
+ if (!host)
+ return 0;
+
+ pcr = host->pcr;
+ pcr->slots[RTSX_SD_CARD].p_dev = NULL;
+ pcr->slots[RTSX_SD_CARD].card_event = NULL;
+ mmc = host->mmc;
+ host->eject = true;
+
+ mutex_lock(&host->host_mutex);
+ if (host->mrq) {
+ dev_dbg(&(pdev->dev),
+ "%s: Controller removed during transfer\n",
+ mmc_hostname(mmc));
+
+ rtsx_pci_complete_unfinished_transfer(pcr);
+
+ host->mrq->cmd->error = -ENOMEDIUM;
+ if (host->mrq->stop)
+ host->mrq->stop->error = -ENOMEDIUM;
+ mmc_request_done(mmc, host->mrq);
+ }
+ mutex_unlock(&host->host_mutex);
+
+ mmc_remove_host(mmc);
+ mmc_free_host(mmc);
+
+ platform_set_drvdata(pdev, NULL);
+
+ dev_dbg(&(pdev->dev),
+ ": Realtek PCI-E SDMMC controller has been removed\n");
+
+ return 0;
+}
+
+static struct platform_device_id rtsx_pci_sdmmc_ids[] = {
+ {
+ .name = DRV_NAME_RTSX_PCI_SDMMC,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids);
+
+static struct platform_driver rtsx_pci_sdmmc_driver = {
+ .probe = rtsx_pci_sdmmc_drv_probe,
+ .remove = rtsx_pci_sdmmc_drv_remove,
+ .id_table = rtsx_pci_sdmmc_ids,
+ .suspend = rtsx_pci_sdmmc_suspend,
+ .resume = rtsx_pci_sdmmc_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME_RTSX_PCI_SDMMC,
+ },
+};
+module_platform_driver(rtsx_pci_sdmmc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E SD/MMC Card Host Driver");
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 4638ddab97b8..63fb265e0da6 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1540,7 +1540,7 @@ static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
#endif /* CONFIG_DEBUG_FS */
-static int __devinit s3cmci_probe(struct platform_device *pdev)
+static int s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
struct mmc_host *mmc;
@@ -1819,7 +1819,7 @@ static void s3cmci_shutdown(struct platform_device *pdev)
clk_disable(host->clk);
}
-static int __devexit s3cmci_remove(struct platform_device *pdev)
+static int s3cmci_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
@@ -1906,7 +1906,7 @@ static struct platform_driver s3cmci_driver = {
},
.id_table = s3cmci_driver_ids,
.probe = s3cmci_probe,
- .remove = __devexit_p(s3cmci_remove),
+ .remove = s3cmci_remove,
.shutdown = s3cmci_shutdown,
};
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
new file mode 100644
index 000000000000..12b0a78497f6
--- /dev/null
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -0,0 +1,312 @@
+/*
+ * Secure Digital Host Controller Interface ACPI driver.
+ *
+ * Copyright (c) 2012, 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/compiler.h>
+#include <linux/stddef.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/acpi.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/pm.h>
+#include <linux/mmc/sdhci.h>
+
+#include "sdhci.h"
+
+enum {
+ SDHCI_ACPI_SD_CD = BIT(0),
+ SDHCI_ACPI_RUNTIME_PM = BIT(1),
+};
+
+struct sdhci_acpi_chip {
+ const struct sdhci_ops *ops;
+ unsigned int quirks;
+ unsigned int quirks2;
+ unsigned long caps;
+ unsigned int caps2;
+ mmc_pm_flag_t pm_caps;
+};
+
+struct sdhci_acpi_slot {
+ const struct sdhci_acpi_chip *chip;
+ unsigned int quirks;
+ unsigned int quirks2;
+ unsigned long caps;
+ unsigned int caps2;
+ mmc_pm_flag_t pm_caps;
+ unsigned int flags;
+};
+
+struct sdhci_acpi_host {
+ struct sdhci_host *host;
+ const struct sdhci_acpi_slot *slot;
+ struct platform_device *pdev;
+ bool use_runtime_pm;
+};
+
+static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
+{
+ return c->slot && (c->slot->flags & flag);
+}
+
+static int sdhci_acpi_enable_dma(struct sdhci_host *host)
+{
+ return 0;
+}
+
+static const struct sdhci_ops sdhci_acpi_ops_dflt = {
+ .enable_dma = sdhci_acpi_enable_dma,
+};
+
+static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
+ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+ .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
+ .flags = SDHCI_ACPI_RUNTIME_PM,
+ .pm_caps = MMC_PM_KEEP_POWER,
+};
+
+static const struct acpi_device_id sdhci_acpi_ids[] = {
+ { "INT33C6", (kernel_ulong_t)&sdhci_acpi_slot_int_sdio },
+ { "PNP0D40" },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
+
+static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
+{
+ const struct acpi_device_id *id;
+
+ for (id = sdhci_acpi_ids; id->id[0]; id++)
+ if (!strcmp(id->id, hid))
+ return (const struct sdhci_acpi_slot *)id->driver_data;
+ return NULL;
+}
+
+static int __devinit sdhci_acpi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ acpi_handle handle = ACPI_HANDLE(dev);
+ struct acpi_device *device;
+ struct sdhci_acpi_host *c;
+ struct sdhci_host *host;
+ struct resource *iomem;
+ resource_size_t len;
+ const char *hid;
+ int err;
+
+ if (acpi_bus_get_device(handle, &device))
+ return -ENODEV;
+
+ if (acpi_bus_get_status(device) || !device->status.present)
+ return -ENODEV;
+
+ hid = acpi_device_hid(device);
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem)
+ return -ENOMEM;
+
+ len = resource_size(iomem);
+ if (len < 0x100)
+ dev_err(dev, "Invalid iomem size!\n");
+
+ if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
+ return -ENOMEM;
+
+ host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host));
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ c = sdhci_priv(host);
+ c->host = host;
+ c->slot = sdhci_acpi_get_slot(hid);
+ c->pdev = pdev;
+ c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
+
+ platform_set_drvdata(pdev, c);
+
+ host->hw_name = "ACPI";
+ host->ops = &sdhci_acpi_ops_dflt;
+ host->irq = platform_get_irq(pdev, 0);
+
+ host->ioaddr = devm_ioremap_nocache(dev, iomem->start,
+ resource_size(iomem));
+ if (host->ioaddr == NULL) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ if (!dev->dma_mask) {
+ u64 dma_mask;
+
+ if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) {
+ /* 64-bit DMA is not supported at present */
+ dma_mask = DMA_BIT_MASK(32);
+ } else {
+ dma_mask = DMA_BIT_MASK(32);
+ }
+
+ dev->dma_mask = &dev->coherent_dma_mask;
+ dev->coherent_dma_mask = dma_mask;
+ }
+
+ if (c->slot) {
+ if (c->slot->chip) {
+ host->ops = c->slot->chip->ops;
+ host->quirks |= c->slot->chip->quirks;
+ host->quirks2 |= c->slot->chip->quirks2;
+ host->mmc->caps |= c->slot->chip->caps;
+ host->mmc->caps2 |= c->slot->chip->caps2;
+ host->mmc->pm_caps |= c->slot->chip->pm_caps;
+ }
+ host->quirks |= c->slot->quirks;
+ host->quirks2 |= c->slot->quirks2;
+ host->mmc->caps |= c->slot->caps;
+ host->mmc->caps2 |= c->slot->caps2;
+ host->mmc->pm_caps |= c->slot->pm_caps;
+ }
+
+ err = sdhci_add_host(host);
+ if (err)
+ goto err_free;
+
+ if (c->use_runtime_pm) {
+ pm_suspend_ignore_children(dev, 1);
+ pm_runtime_set_autosuspend_delay(dev, 50);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+ }
+
+ return 0;
+
+err_free:
+ platform_set_drvdata(pdev, NULL);
+ sdhci_free_host(c->host);
+ return err;
+}
+
+static int __devexit sdhci_acpi_remove(struct platform_device *pdev)
+{
+ struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int dead;
+
+ if (c->use_runtime_pm) {
+ pm_runtime_get_sync(dev);
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+ }
+
+ dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0);
+ sdhci_remove_host(c->host, dead);
+ platform_set_drvdata(pdev, NULL);
+ sdhci_free_host(c->host);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int sdhci_acpi_suspend(struct device *dev)
+{
+ struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+ return sdhci_suspend_host(c->host);
+}
+
+static int sdhci_acpi_resume(struct device *dev)
+{
+ struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+ return sdhci_resume_host(c->host);
+}
+
+#else
+
+#define sdhci_acpi_suspend NULL
+#define sdhci_acpi_resume NULL
+
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_acpi_runtime_suspend(struct device *dev)
+{
+ struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+ return sdhci_runtime_suspend_host(c->host);
+}
+
+static int sdhci_acpi_runtime_resume(struct device *dev)
+{
+ struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+ return sdhci_runtime_resume_host(c->host);
+}
+
+static int sdhci_acpi_runtime_idle(struct device *dev)
+{
+ return 0;
+}
+
+#else
+
+#define sdhci_acpi_runtime_suspend NULL
+#define sdhci_acpi_runtime_resume NULL
+#define sdhci_acpi_runtime_idle NULL
+
+#endif
+
+static const struct dev_pm_ops sdhci_acpi_pm_ops = {
+ .suspend = sdhci_acpi_suspend,
+ .resume = sdhci_acpi_resume,
+ .runtime_suspend = sdhci_acpi_runtime_suspend,
+ .runtime_resume = sdhci_acpi_runtime_resume,
+ .runtime_idle = sdhci_acpi_runtime_idle,
+};
+
+static struct platform_driver sdhci_acpi_driver = {
+ .driver = {
+ .name = "sdhci-acpi",
+ .owner = THIS_MODULE,
+ .acpi_match_table = sdhci_acpi_ids,
+ .pm = &sdhci_acpi_pm_ops,
+ },
+ .probe = sdhci_acpi_probe,
+ .remove = __devexit_p(sdhci_acpi_remove),
+};
+
+module_platform_driver(sdhci_acpi_driver);
+
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
index 28a870804f60..30bfdc4ae52a 100644
--- a/drivers/mmc/host/sdhci-cns3xxx.c
+++ b/drivers/mmc/host/sdhci-cns3xxx.c
@@ -95,12 +95,12 @@ static struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
SDHCI_QUIRK_NONSTANDARD_CLOCK,
};
-static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
+static int sdhci_cns3xxx_probe(struct platform_device *pdev)
{
return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
}
-static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
+static int sdhci_cns3xxx_remove(struct platform_device *pdev)
{
return sdhci_pltfm_unregister(pdev);
}
@@ -112,7 +112,7 @@ static struct platform_driver sdhci_cns3xxx_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_cns3xxx_probe,
- .remove = __devexit_p(sdhci_cns3xxx_remove),
+ .remove = sdhci_cns3xxx_remove,
};
module_platform_driver(sdhci_cns3xxx_driver);
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 8fd50a211037..169fab91778e 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -19,20 +19,30 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/err.h>
-#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
#include <linux/mmc/host.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include "sdhci-pltfm.h"
struct sdhci_dove_priv {
struct clk *clk;
+ int gpio_cd;
};
+static irqreturn_t sdhci_dove_carddetect_irq(int irq, void *data)
+{
+ struct sdhci_host *host = data;
+
+ tasklet_schedule(&host->card_tasklet);
+ return IRQ_HANDLED;
+}
+
static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
{
u16 ret;
@@ -50,16 +60,25 @@ static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_dove_priv *priv = pltfm_host->priv;
u32 ret;
+ ret = readl(host->ioaddr + reg);
+
switch (reg) {
case SDHCI_CAPABILITIES:
- ret = readl(host->ioaddr + reg);
/* Mask the support for 3.0V */
ret &= ~SDHCI_CAN_VDD_300;
break;
- default:
- ret = readl(host->ioaddr + reg);
+ case SDHCI_PRESENT_STATE:
+ if (gpio_is_valid(priv->gpio_cd)) {
+ if (gpio_get_value(priv->gpio_cd) == 0)
+ ret |= SDHCI_CARD_PRESENT;
+ else
+ ret &= ~SDHCI_CARD_PRESENT;
+ }
+ break;
}
return ret;
}
@@ -78,7 +97,7 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {
SDHCI_QUIRK_NO_HISPD_BIT,
};
-static int __devinit sdhci_dove_probe(struct platform_device *pdev)
+static int sdhci_dove_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
@@ -92,29 +111,74 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
return -ENOMEM;
}
- priv->clk = clk_get(&pdev->dev, NULL);
- if (!IS_ERR(priv->clk))
- clk_prepare_enable(priv->clk);
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
- ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
- if (ret)
- goto sdhci_dove_register_fail;
+ if (pdev->dev.of_node) {
+ priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node,
+ "cd-gpios", 0);
+ } else {
+ priv->gpio_cd = -EINVAL;
+ }
+
+ if (gpio_is_valid(priv->gpio_cd)) {
+ ret = gpio_request(priv->gpio_cd, "sdhci-cd");
+ if (ret) {
+ dev_err(&pdev->dev, "card detect gpio request failed: %d\n",
+ ret);
+ return ret;
+ }
+ gpio_direction_input(priv->gpio_cd);
+ }
+
+ host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata);
+ if (IS_ERR(host)) {
+ ret = PTR_ERR(host);
+ goto err_sdhci_pltfm_init;
+ }
- host = platform_get_drvdata(pdev);
pltfm_host = sdhci_priv(host);
pltfm_host->priv = priv;
+ if (!IS_ERR(priv->clk))
+ clk_prepare_enable(priv->clk);
+
+ sdhci_get_of_property(pdev);
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ goto err_sdhci_add;
+
+ /*
+ * We must request the IRQ after sdhci_add_host(), as the tasklet only
+ * gets setup in sdhci_add_host() and we oops.
+ */
+ if (gpio_is_valid(priv->gpio_cd)) {
+ ret = request_irq(gpio_to_irq(priv->gpio_cd),
+ sdhci_dove_carddetect_irq,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ mmc_hostname(host->mmc), host);
+ if (ret) {
+ dev_err(&pdev->dev, "card detect irq request failed: %d\n",
+ ret);
+ goto err_request_irq;
+ }
+ }
+
return 0;
-sdhci_dove_register_fail:
- if (!IS_ERR(priv->clk)) {
+err_request_irq:
+ sdhci_remove_host(host, 0);
+err_sdhci_add:
+ if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
- }
+ sdhci_pltfm_free(pdev);
+err_sdhci_pltfm_init:
+ if (gpio_is_valid(priv->gpio_cd))
+ gpio_free(priv->gpio_cd);
return ret;
}
-static int __devexit sdhci_dove_remove(struct platform_device *pdev)
+static int sdhci_dove_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -122,14 +186,18 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
sdhci_pltfm_unregister(pdev);
- if (!IS_ERR(priv->clk)) {
- clk_disable_unprepare(priv->clk);
- clk_put(priv->clk);
+ if (gpio_is_valid(priv->gpio_cd)) {
+ free_irq(gpio_to_irq(priv->gpio_cd), host);
+ gpio_free(priv->gpio_cd);
}
+
+ if (!IS_ERR(priv->clk))
+ clk_disable_unprepare(priv->clk);
+
return 0;
}
-static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
+static const struct of_device_id sdhci_dove_of_match_table[] = {
{ .compatible = "marvell,dove-sdhci", },
{}
};
@@ -143,7 +211,7 @@ static struct platform_driver sdhci_dove_driver = {
.of_match_table = of_match_ptr(sdhci_dove_of_match_table),
},
.probe = sdhci_dove_probe,
- .remove = __devexit_p(sdhci_dove_remove),
+ .remove = sdhci_dove_remove,
};
module_platform_driver(sdhci_dove_driver);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index effc2acfe778..e07df812ff1e 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -403,7 +403,7 @@ static irqreturn_t cd_irq(int irq, void *data)
};
#ifdef CONFIG_OF
-static int __devinit
+static int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
struct esdhc_platform_data *boarddata)
{
@@ -440,7 +440,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
}
#endif
-static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
+static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
@@ -456,10 +456,10 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
- imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+ imx_data = devm_kzalloc(&pdev->dev, sizeof(*imx_data), GFP_KERNEL);
if (!imx_data) {
err = -ENOMEM;
- goto err_imx_data;
+ goto free_sdhci;
}
if (of_id)
@@ -470,19 +470,19 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(imx_data->clk_ipg)) {
err = PTR_ERR(imx_data->clk_ipg);
- goto err_clk_get;
+ goto free_sdhci;
}
imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
if (IS_ERR(imx_data->clk_ahb)) {
err = PTR_ERR(imx_data->clk_ahb);
- goto err_clk_get;
+ goto free_sdhci;
}
imx_data->clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(imx_data->clk_per)) {
err = PTR_ERR(imx_data->clk_per);
- goto err_clk_get;
+ goto free_sdhci;
}
pltfm_host->clk = imx_data->clk_per;
@@ -494,7 +494,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
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;
+ goto disable_clk;
}
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
@@ -519,7 +519,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (!host->mmc->parent->platform_data) {
dev_err(mmc_dev(host->mmc), "no board data!\n");
err = -EINVAL;
- goto no_board_data;
+ goto disable_clk;
}
imx_data->boarddata = *((struct esdhc_platform_data *)
host->mmc->parent->platform_data);
@@ -527,7 +527,8 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
/* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) {
- err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+ err = devm_gpio_request_one(&pdev->dev, boarddata->wp_gpio,
+ GPIOF_IN, "ESDHC_WP");
if (err) {
dev_warn(mmc_dev(host->mmc),
"no write-protect pin available!\n");
@@ -543,19 +544,21 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
switch (boarddata->cd_type) {
case ESDHC_CD_GPIO:
- err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+ err = devm_gpio_request_one(&pdev->dev, boarddata->cd_gpio,
+ GPIOF_IN, "ESDHC_CD");
if (err) {
dev_err(mmc_dev(host->mmc),
"no card-detect pin available!\n");
- goto no_card_detect_pin;
+ goto disable_clk;
}
- err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+ err = devm_request_irq(&pdev->dev,
+ gpio_to_irq(boarddata->cd_gpio), cd_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
mmc_hostname(host->mmc), host);
if (err) {
dev_err(mmc_dev(host->mmc), "request irq error\n");
- goto no_card_detect_irq;
+ goto disable_clk;
}
/* fall through */
@@ -574,55 +577,32 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
err = sdhci_add_host(host);
if (err)
- goto err_add_host;
+ goto disable_clk;
return 0;
-err_add_host:
- if (gpio_is_valid(boarddata->cd_gpio))
- free_irq(gpio_to_irq(boarddata->cd_gpio), host);
-no_card_detect_irq:
- if (gpio_is_valid(boarddata->cd_gpio))
- gpio_free(boarddata->cd_gpio);
- if (gpio_is_valid(boarddata->wp_gpio))
- gpio_free(boarddata->wp_gpio);
-no_card_detect_pin:
-no_board_data:
-pin_err:
+disable_clk:
clk_disable_unprepare(imx_data->clk_per);
clk_disable_unprepare(imx_data->clk_ipg);
clk_disable_unprepare(imx_data->clk_ahb);
-err_clk_get:
- kfree(imx_data);
-err_imx_data:
+free_sdhci:
sdhci_pltfm_free(pdev);
return err;
}
-static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
+static int sdhci_esdhc_imx_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
- struct esdhc_platform_data *boarddata = &imx_data->boarddata;
int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
sdhci_remove_host(host, dead);
- if (gpio_is_valid(boarddata->wp_gpio))
- gpio_free(boarddata->wp_gpio);
-
- if (gpio_is_valid(boarddata->cd_gpio)) {
- free_irq(gpio_to_irq(boarddata->cd_gpio), host);
- gpio_free(boarddata->cd_gpio);
- }
-
clk_disable_unprepare(imx_data->clk_per);
clk_disable_unprepare(imx_data->clk_ipg);
clk_disable_unprepare(imx_data->clk_ahb);
- kfree(imx_data);
-
sdhci_pltfm_free(pdev);
return 0;
@@ -637,7 +617,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
},
.id_table = imx_esdhc_devtype,
.probe = sdhci_esdhc_imx_probe,
- .remove = __devexit_p(sdhci_esdhc_imx_remove),
+ .remove = sdhci_esdhc_imx_remove,
};
module_platform_driver(sdhci_esdhc_imx_driver);
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 63d219f57cae..f32526d2d966 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -22,6 +22,7 @@
#include "sdhci-esdhc.h"
#define VENDOR_V_22 0x12
+#define VENDOR_V_23 0x13
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
@@ -85,6 +86,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
return ret;
}
+static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+ /*
+ * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+ * when SYSCTL[RSTD]) is set for some special operations.
+ * No any impact other operation.
+ */
+ if (reg == SDHCI_INT_ENABLE)
+ val |= SDHCI_INT_BLK_GAP;
+ sdhci_be32bs_writel(host, val, reg);
+}
+
static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
{
if (reg == SDHCI_BLOCK_SIZE) {
@@ -121,6 +134,41 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
sdhci_be32bs_writeb(host, val, reg);
}
+/*
+ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
+ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
+ * and Block Gap Event(IRQSTAT[BGE]) are also set.
+ * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+ * and re-issue the entire read transaction from beginning.
+ */
+static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+{
+ u32 tmp;
+ bool applicable;
+ dma_addr_t dmastart;
+ dma_addr_t dmanow;
+
+ tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+ tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+
+ applicable = (intmask & SDHCI_INT_DATA_END) &&
+ (intmask & SDHCI_INT_BLK_GAP) &&
+ (tmp == VENDOR_V_23);
+ if (!applicable)
+ return;
+
+ host->data->error = 0;
+ dmastart = sg_dma_address(host->data->sg);
+ dmanow = dmastart + host->data->bytes_xfered;
+ /*
+ * Force update to the next DMA block boundary.
+ */
+ dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+ SDHCI_DEFAULT_BOUNDARY_SIZE;
+ host->data->bytes_xfered = dmanow - dmastart;
+ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+}
+
static int esdhc_of_enable_dma(struct sdhci_host *host)
{
setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
@@ -177,13 +225,16 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
if (vvn == VENDOR_V_22)
host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+ if (vvn > VENDOR_V_22)
+ host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
}
static struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl,
.read_w = esdhc_readw,
.read_b = esdhc_readb,
- .write_l = sdhci_be32bs_writel,
+ .write_l = esdhc_writel,
.write_w = esdhc_writew,
.write_b = esdhc_writeb,
.set_clock = esdhc_of_set_clock,
@@ -195,6 +246,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
#endif
+ .adma_workaround = esdhci_of_adma_workaround,
};
static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
@@ -208,12 +260,12 @@ static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
.ops = &sdhci_esdhc_ops,
};
-static int __devinit sdhci_esdhc_probe(struct platform_device *pdev)
+static int sdhci_esdhc_probe(struct platform_device *pdev)
{
return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
}
-static int __devexit sdhci_esdhc_remove(struct platform_device *pdev)
+static int sdhci_esdhc_remove(struct platform_device *pdev)
{
return sdhci_pltfm_unregister(pdev);
}
@@ -234,7 +286,7 @@ static struct platform_driver sdhci_esdhc_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_esdhc_probe,
- .remove = __devexit_p(sdhci_esdhc_remove),
+ .remove = sdhci_esdhc_remove,
};
module_platform_driver(sdhci_esdhc_driver);
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
index 0ce088ae0228..c3d3715ec3d7 100644
--- a/drivers/mmc/host/sdhci-of-hlwd.c
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -66,12 +66,12 @@ static struct sdhci_pltfm_data sdhci_hlwd_pdata = {
.ops = &sdhci_hlwd_ops,
};
-static int __devinit sdhci_hlwd_probe(struct platform_device *pdev)
+static int sdhci_hlwd_probe(struct platform_device *pdev)
{
return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
}
-static int __devexit sdhci_hlwd_remove(struct platform_device *pdev)
+static int sdhci_hlwd_remove(struct platform_device *pdev)
{
return sdhci_pltfm_unregister(pdev);
}
@@ -90,7 +90,7 @@ static struct platform_driver sdhci_hlwd_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_hlwd_probe,
- .remove = __devexit_p(sdhci_hlwd_remove),
+ .remove = sdhci_hlwd_remove,
};
module_platform_driver(sdhci_hlwd_driver);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 04936f353ced..c7dd0cbc99de 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -114,6 +114,7 @@ static int ricoh_mmc_probe_slot(struct sdhci_pci_slot *slot)
SDHCI_TIMEOUT_CLK_UNIT |
SDHCI_CAN_VDD_330 |
+ SDHCI_CAN_DO_HISPD |
SDHCI_CAN_DO_SDMA;
return 0;
}
@@ -653,7 +654,7 @@ static const struct sdhci_pci_fixes sdhci_via = {
.probe = via_probe,
};
-static const struct pci_device_id pci_ids[] __devinitconst = {
+static const struct pci_device_id pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_RICOH,
.device = PCI_DEVICE_ID_RICOH_R5C822,
@@ -1183,7 +1184,7 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
* *
\*****************************************************************************/
-static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
+static struct sdhci_pci_slot *sdhci_pci_probe_slot(
struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
int slotno)
{
@@ -1338,7 +1339,7 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
sdhci_free_host(slot->host);
}
-static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
+static void sdhci_pci_runtime_pm_allow(struct device *dev)
{
pm_runtime_put_noidle(dev);
pm_runtime_allow(dev);
@@ -1347,13 +1348,13 @@ static void __devinit sdhci_pci_runtime_pm_allow(struct device *dev)
pm_suspend_ignore_children(dev, 1);
}
-static void __devexit sdhci_pci_runtime_pm_forbid(struct device *dev)
+static void sdhci_pci_runtime_pm_forbid(struct device *dev)
{
pm_runtime_forbid(dev);
pm_runtime_get_noresume(dev);
}
-static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
+static int sdhci_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct sdhci_pci_chip *chip;
@@ -1445,7 +1446,7 @@ err:
return ret;
}
-static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
+static void sdhci_pci_remove(struct pci_dev *pdev)
{
int i;
struct sdhci_pci_chip *chip;
@@ -1470,7 +1471,7 @@ static struct pci_driver sdhci_driver = {
.name = "sdhci-pci",
.id_table = pci_ids,
.probe = sdhci_pci_probe,
- .remove = __devexit_p(sdhci_pci_remove),
+ .remove = sdhci_pci_remove,
.driver = {
.pm = &sdhci_pci_pm_ops
},
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 27164457f861..d4283ef5917a 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -78,6 +78,9 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (of_get_property(np, "broken-cd", NULL))
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ if (of_get_property(np, "no-1-8-v", NULL))
+ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+
if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
@@ -89,6 +92,12 @@ void sdhci_get_of_property(struct platform_device *pdev)
clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk)
pltfm_host->clock = be32_to_cpup(clk);
+
+ if (of_find_property(np, "keep-power-in-suspend", NULL))
+ host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
+
+ if (of_find_property(np, "enable-sdio-wakeup", NULL))
+ host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
}
}
#else
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
index 8e63a9c04e31..ac854aa192a8 100644
--- a/drivers/mmc/host/sdhci-pxav2.c
+++ b/drivers/mmc/host/sdhci-pxav2.c
@@ -166,7 +166,7 @@ static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
}
#endif
-static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
+static int sdhci_pxav2_probe(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
@@ -247,7 +247,7 @@ err_clk_get:
return ret;
}
-static int __devexit sdhci_pxav2_remove(struct platform_device *pdev)
+static int sdhci_pxav2_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -275,7 +275,7 @@ static struct platform_driver sdhci_pxav2_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_pxav2_probe,
- .remove = __devexit_p(sdhci_pxav2_remove),
+ .remove = sdhci_pxav2_remove,
};
module_platform_driver(sdhci_pxav2_driver);
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index e918a2bb3af1..fad0966427fd 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -163,10 +163,18 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
return 0;
}
+static u32 pxav3_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ return clk_get_rate(pltfm_host->clk);
+}
+
static struct sdhci_ops pxav3_sdhci_ops = {
.platform_reset_exit = pxav3_set_private_registers,
.set_uhs_signaling = pxav3_set_uhs_signaling,
.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+ .get_max_clock = pxav3_get_max_clock,
};
#ifdef CONFIG_OF
@@ -214,7 +222,7 @@ static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
}
#endif
-static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
+static int sdhci_pxav3_probe(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
@@ -249,7 +257,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
- | SDHCI_QUIRK_32BIT_ADMA_SIZE;
+ | SDHCI_QUIRK_32BIT_ADMA_SIZE
+ | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
/* enable 1/8V DDR capable */
host->mmc->caps |= MMC_CAP_1_8V_DDR;
@@ -271,6 +280,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
if (pdata->quirks)
host->quirks |= pdata->quirks;
+ if (pdata->quirks2)
+ host->quirks2 |= pdata->quirks2;
if (pdata->host_caps)
host->mmc->caps |= pdata->host_caps;
if (pdata->host_caps2)
@@ -313,7 +324,7 @@ err_clk_get:
return ret;
}
-static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
+static int sdhci_pxav3_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -346,7 +357,7 @@ static struct platform_driver sdhci_pxav3_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_pxav3_probe,
- .remove = __devexit_p(sdhci_pxav3_remove),
+ .remove = sdhci_pxav3_remove,
};
module_platform_driver(sdhci_pxav3_driver);
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index a54dd5d7a5f9..82a8de148a8f 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -24,6 +24,7 @@
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/mmc/host.h>
@@ -57,6 +58,7 @@ struct sdhci_s3c {
int ext_cd_irq;
int ext_cd_gpio;
int *gpios;
+ struct pinctrl *pctrl;
struct clk *clk_io;
struct clk *clk_bus[MAX_BUS_CLK];
@@ -373,18 +375,27 @@ static struct sdhci_ops sdhci_s3c_ops = {
static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
{
struct sdhci_host *host = platform_get_drvdata(dev);
+#ifdef CONFIG_PM_RUNTIME
+ struct sdhci_s3c *sc = sdhci_priv(host);
+#endif
unsigned long flags;
if (host) {
spin_lock_irqsave(&host->lock, flags);
if (state) {
dev_dbg(&dev->dev, "card inserted.\n");
+#ifdef CONFIG_PM_RUNTIME
+ clk_prepare_enable(sc->clk_io);
+#endif
host->flags &= ~SDHCI_DEVICE_DEAD;
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
} else {
dev_dbg(&dev->dev, "card removed.\n");
host->flags |= SDHCI_DEVICE_DEAD;
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+#ifdef CONFIG_PM_RUNTIME
+ clk_disable_unprepare(sc->clk_io);
+#endif
}
tasklet_schedule(&host->card_tasklet);
spin_unlock_irqrestore(&host->lock, flags);
@@ -406,7 +417,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
struct s3c_sdhci_platdata *pdata = sc->pdata;
struct device *dev = &sc->pdev->dev;
- if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
+ if (devm_gpio_request(dev, pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
sc->ext_cd_gpio = pdata->ext_cd_gpio;
sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio);
if (sc->ext_cd_irq &&
@@ -430,7 +441,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
}
#ifdef CONFIG_OF
-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+static int sdhci_s3c_parse_dt(struct device *dev,
struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
{
struct device_node *node = dev->of_node;
@@ -449,12 +460,12 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
return -ENOMEM;
/* get the card detection method */
- if (of_get_property(node, "broken-cd", 0)) {
+ if (of_get_property(node, "broken-cd", NULL)) {
pdata->cd_type = S3C_SDHCI_CD_NONE;
goto setup_bus;
}
- if (of_get_property(node, "non-removable", 0)) {
+ if (of_get_property(node, "non-removable", NULL)) {
pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
goto setup_bus;
}
@@ -477,8 +488,9 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
return -EINVAL;
}
- dev_info(dev, "assuming no card detect line available\n");
- pdata->cd_type = S3C_SDHCI_CD_NONE;
+ /* assuming internal card detect that will be configured by pinctrl */
+ pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
+ goto setup_bus;
found_cd:
if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
@@ -487,7 +499,7 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
if (of_get_property(node, "cd-inverted", NULL))
pdata->ext_cd_gpio_invert = 1;
} else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
- ret = gpio_request(gpio, "sdhci-cd");
+ ret = devm_gpio_request(dev, gpio, "sdhci-cd");
if (ret) {
dev_err(dev, "card detect gpio request failed\n");
return -EINVAL;
@@ -496,36 +508,31 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
}
setup_bus:
+ if (!IS_ERR(ourhost->pctrl))
+ return 0;
+
/* get the gpios for command, clock and data lines */
for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
gpio = of_get_gpio(node, cnt);
if (!gpio_is_valid(gpio)) {
dev_err(dev, "invalid gpio[%d]\n", cnt);
- goto err_free_dt_cd_gpio;
+ return -EINVAL;
}
ourhost->gpios[cnt] = gpio;
}
for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
- ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio");
+ ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio");
if (ret) {
dev_err(dev, "gpio[%d] request failed\n", cnt);
- goto err_free_dt_gpios;
+ return -EINVAL;
}
}
return 0;
-
- err_free_dt_gpios:
- while (--cnt >= 0)
- gpio_free(ourhost->gpios[cnt]);
- err_free_dt_cd_gpio:
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
- gpio_free(ourhost->ext_cd_gpio);
- return -EINVAL;
}
#else
-static int __devinit sdhci_s3c_parse_dt(struct device *dev,
+static int sdhci_s3c_parse_dt(struct device *dev,
struct sdhci_host *host, struct s3c_sdhci_platdata *pdata)
{
return -EINVAL;
@@ -548,7 +555,7 @@ static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
platform_get_device_id(pdev)->driver_data;
}
-static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
+static int sdhci_s3c_probe(struct platform_device *pdev)
{
struct s3c_sdhci_platdata *pdata;
struct sdhci_s3c_drv_data *drv_data;
@@ -579,13 +586,15 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
ret = -ENOMEM;
- goto err_pdata;
+ goto err_pdata_io_clk;
}
+ sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev);
+
if (pdev->dev.of_node) {
ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
if (ret)
- goto err_pdata;
+ goto err_pdata_io_clk;
} else {
memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
sc->ext_cd_gpio = -1; /* invalid gpio number */
@@ -603,7 +612,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
if (IS_ERR(sc->clk_io)) {
dev_err(dev, "failed to get io clock\n");
ret = PTR_ERR(sc->clk_io);
- goto err_io_clk;
+ goto err_pdata_io_clk;
}
/* enable the local io clock and keep it running for the moment. */
@@ -766,19 +775,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
- err_io_clk:
- for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
- gpio_free(sc->gpios[ptr]);
- if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
- gpio_free(sc->ext_cd_gpio);
-
- err_pdata:
+ err_pdata_io_clk:
sdhci_free_host(host);
return ret;
}
-static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
+static int sdhci_s3c_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_s3c *sc = sdhci_priv(host);
@@ -791,9 +794,6 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
if (sc->ext_cd_irq)
free_irq(sc->ext_cd_irq, sc);
- if (gpio_is_valid(sc->ext_cd_gpio))
- gpio_free(sc->ext_cd_gpio);
-
#ifdef CONFIG_PM_RUNTIME
if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
clk_prepare_enable(sc->clk_io);
@@ -814,11 +814,6 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
clk_disable_unprepare(sc->clk_io);
clk_put(sc->clk_io);
- if (pdev->dev.of_node) {
- for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
- gpio_free(sc->gpios[ptr]);
- }
-
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
@@ -916,7 +911,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match);
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
- .remove = __devexit_p(sdhci_s3c_remove),
+ .remove = sdhci_s3c_remove,
.id_table = sdhci_s3c_driver_ids,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
index 6be89c032deb..c6ece0bd03b3 100644
--- a/drivers/mmc/host/sdhci-spear.c
+++ b/drivers/mmc/host/sdhci-spear.c
@@ -71,8 +71,7 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id)
}
#ifdef CONFIG_OF
-static struct sdhci_plat_data * __devinit
-sdhci_probe_config_dt(struct platform_device *pdev)
+static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct sdhci_plat_data *pdata = NULL;
@@ -96,14 +95,13 @@ sdhci_probe_config_dt(struct platform_device *pdev)
return pdata;
}
#else
-static struct sdhci_plat_data * __devinit
-sdhci_probe_config_dt(struct platform_device *pdev)
+static struct sdhci_plat_data *sdhci_probe_config_dt(struct platform_device *pdev)
{
return ERR_PTR(-ENOSYS);
}
#endif
-static int __devinit sdhci_probe(struct platform_device *pdev)
+static int sdhci_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct sdhci_host *host;
@@ -146,6 +144,11 @@ static int __devinit sdhci_probe(struct platform_device *pdev)
goto put_clk;
}
+ ret = clk_set_rate(sdhci->clk, 50000000);
+ if (ret)
+ dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n",
+ clk_get_rate(sdhci->clk));
+
if (np) {
sdhci->data = sdhci_probe_config_dt(pdev);
if (IS_ERR(sdhci->data)) {
@@ -268,7 +271,7 @@ err:
return ret;
}
-static int __devexit sdhci_remove(struct platform_device *pdev)
+static int sdhci_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev);
@@ -297,7 +300,7 @@ static int sdhci_suspend(struct device *dev)
ret = sdhci_suspend_host(host);
if (!ret)
- clk_disable_unprepare(sdhci->clk);
+ clk_disable(sdhci->clk);
return ret;
}
@@ -308,7 +311,7 @@ static int sdhci_resume(struct device *dev)
struct spear_sdhci *sdhci = dev_get_platdata(dev);
int ret;
- ret = clk_prepare_enable(sdhci->clk);
+ ret = clk_enable(sdhci->clk);
if (ret) {
dev_dbg(dev, "Resume: Error enabling clock\n");
return ret;
@@ -336,7 +339,7 @@ static struct platform_driver sdhci_driver = {
.of_match_table = of_match_ptr(sdhci_spear_id_table),
},
.probe = sdhci_probe,
- .remove = __devexit_p(sdhci_remove),
+ .remove = sdhci_remove,
};
module_platform_driver(sdhci_driver);
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index f9eb91623701..3695b2e0cbd2 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -206,7 +206,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra30 = {
};
#endif
-static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
+static const struct of_device_id sdhci_tegra_dt_match[] = {
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
#endif
@@ -217,7 +217,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] __devinitdata = {
};
MODULE_DEVICE_TABLE(of, sdhci_dt_ids);
-static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
+static struct tegra_sdhci_platform_data *sdhci_tegra_dt_parse_pdata(
struct platform_device *pdev)
{
struct tegra_sdhci_platform_data *plat;
@@ -244,7 +244,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
return plat;
}
-static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
+static int sdhci_tegra_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct sdhci_tegra_soc_data *soc_data;
@@ -370,7 +370,7 @@ err_no_plat:
return rc;
}
-static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
+static int sdhci_tegra_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -407,7 +407,7 @@ static struct platform_driver sdhci_tegra_driver = {
.pm = SDHCI_PLTFM_PMOPS,
},
.probe = sdhci_tegra_probe,
- .remove = __devexit_p(sdhci_tegra_remove),
+ .remove = sdhci_tegra_remove,
};
module_platform_driver(sdhci_tegra_driver);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c7851c0aabce..6f0bfc0c8c9c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1618,7 +1618,7 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
if (host->vqmmc) {
- ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000);
+ ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
if (ret) {
pr_warning("%s: Switching to 3.3V signalling voltage "
" failed\n", mmc_hostname(host->mmc));
@@ -1662,7 +1662,7 @@ static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
*/
if (host->vqmmc)
ret = regulator_set_voltage(host->vqmmc,
- 1800000, 1800000);
+ 1700000, 1950000);
else
ret = 0;
@@ -1994,30 +1994,11 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
sdhci_runtime_pm_put(host);
}
-static const struct mmc_host_ops sdhci_ops = {
- .request = sdhci_request,
- .set_ios = sdhci_set_ios,
- .get_ro = sdhci_get_ro,
- .hw_reset = sdhci_hw_reset,
- .enable_sdio_irq = sdhci_enable_sdio_irq,
- .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
- .execute_tuning = sdhci_execute_tuning,
- .enable_preset_value = sdhci_enable_preset_value,
-};
-
-/*****************************************************************************\
- * *
- * Tasklets *
- * *
-\*****************************************************************************/
-
-static void sdhci_tasklet_card(unsigned long param)
+static void sdhci_card_event(struct mmc_host *mmc)
{
- struct sdhci_host *host;
+ struct sdhci_host *host = mmc_priv(mmc);
unsigned long flags;
- host = (struct sdhci_host*)param;
-
spin_lock_irqsave(&host->lock, flags);
/* Check host->mrq first in case we are runtime suspended */
@@ -2036,6 +2017,31 @@ static void sdhci_tasklet_card(unsigned long param)
}
spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops sdhci_ops = {
+ .request = sdhci_request,
+ .set_ios = sdhci_set_ios,
+ .get_ro = sdhci_get_ro,
+ .hw_reset = sdhci_hw_reset,
+ .enable_sdio_irq = sdhci_enable_sdio_irq,
+ .start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
+ .execute_tuning = sdhci_execute_tuning,
+ .enable_preset_value = sdhci_enable_preset_value,
+ .card_event = sdhci_card_event,
+};
+
+/*****************************************************************************\
+ * *
+ * Tasklets *
+ * *
+\*****************************************************************************/
+
+static void sdhci_tasklet_card(unsigned long param)
+{
+ struct sdhci_host *host = (struct sdhci_host*)param;
+
+ sdhci_card_event(host->mmc);
mmc_detect_change(host->mmc, msecs_to_jiffies(200));
}
@@ -2282,6 +2288,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
+ if (host->ops->adma_workaround)
+ host->ops->adma_workaround(host, intmask);
}
if (host->data->error)
@@ -2858,10 +2866,16 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_hostname(mmc));
host->vqmmc = NULL;
}
- }
- else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
+ } else {
regulator_enable(host->vqmmc);
- else
+ if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
+ 1950000))
+ caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_SDR50 |
+ SDHCI_SUPPORT_DDR50);
+ }
+
+ if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
SDHCI_SUPPORT_DDR50);
@@ -2919,21 +2933,18 @@ int sdhci_add_host(struct sdhci_host *host)
mmc_hostname(mmc));
host->vmmc = NULL;
}
- } else
- regulator_enable(host->vmmc);
+ }
#ifdef CONFIG_REGULATOR
if (host->vmmc) {
- ret = regulator_is_supported_voltage(host->vmmc, 3300000,
- 3300000);
+ ret = regulator_is_supported_voltage(host->vmmc, 2700000,
+ 3600000);
if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
caps[0] &= ~SDHCI_CAN_VDD_330;
- ret = regulator_is_supported_voltage(host->vmmc, 3000000,
- 3000000);
if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
caps[0] &= ~SDHCI_CAN_VDD_300;
- ret = regulator_is_supported_voltage(host->vmmc, 1800000,
- 1800000);
+ ret = regulator_is_supported_voltage(host->vmmc, 1700000,
+ 1950000);
if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
caps[0] &= ~SDHCI_CAN_VDD_180;
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 71a4a7ed46c5..a6d69b7bdea2 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -120,6 +120,7 @@
#define SDHCI_SIGNAL_ENABLE 0x38
#define SDHCI_INT_RESPONSE 0x00000001
#define SDHCI_INT_DATA_END 0x00000002
+#define SDHCI_INT_BLK_GAP 0x00000004
#define SDHCI_INT_DMA_END 0x00000008
#define SDHCI_INT_SPACE_AVAIL 0x00000010
#define SDHCI_INT_DATA_AVAIL 0x00000020
@@ -146,7 +147,8 @@
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
+ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
+ SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
@@ -278,6 +280,7 @@ struct sdhci_ops {
void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
void (*platform_init)(struct sdhci_host *host);
};
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d25bc97dc5c6..9a4c151067dd 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1104,7 +1104,6 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
struct mmc_request *mrq = host->mrq;
- struct mmc_data *data = mrq->data;
cancel_delayed_work_sync(&host->timeout_work);
@@ -1152,13 +1151,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
case MMCIF_WAIT_FOR_READ_END:
case MMCIF_WAIT_FOR_WRITE_END:
if (host->sd_error)
- data->error = sh_mmcif_error_manage(host);
+ mrq->data->error = sh_mmcif_error_manage(host);
break;
default:
BUG();
}
if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
+ struct mmc_data *data = mrq->data;
if (!mrq->cmd->error && data && !data->error)
data->bytes_xfered =
data->blocks * data->blksz;
@@ -1231,10 +1231,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
host->sd_error = true;
dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
}
- if (host->state == STATE_IDLE) {
- dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state);
- return IRQ_HANDLED;
- }
if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
if (!host->dma_active)
return IRQ_WAKE_THREAD;
@@ -1302,7 +1298,7 @@ static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
}
-static int __devinit sh_mmcif_probe(struct platform_device *pdev)
+static int sh_mmcif_probe(struct platform_device *pdev)
{
int ret = 0, irq[2];
struct mmc_host *mmc;
@@ -1310,7 +1306,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
struct resource *res;
void __iomem *reg;
- char clk_name[8];
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq(pdev, 1);
@@ -1360,11 +1355,10 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
host->power = false;
- snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
- host->hclk = clk_get(&pdev->dev, clk_name);
+ host->hclk = clk_get(&pdev->dev, NULL);
if (IS_ERR(host->hclk)) {
ret = PTR_ERR(host->hclk);
- dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
+ dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
goto eclkget;
}
ret = sh_mmcif_clk_update(host);
@@ -1430,7 +1424,7 @@ ealloch:
return ret;
}
-static int __devexit sh_mmcif_remove(struct platform_device *pdev)
+static int sh_mmcif_remove(struct platform_device *pdev)
{
struct sh_mmcif_host *host = platform_get_drvdata(pdev);
struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 0bdc146178db..524a7f773820 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -117,13 +117,12 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
.cd_wakeup = sh_mobile_sdhi_cd_wakeup,
};
-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+static int sh_mobile_sdhi_probe(struct platform_device *pdev)
{
struct sh_mobile_sdhi *priv;
struct tmio_mmc_data *mmc_data;
struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
struct tmio_mmc_host *host;
- char clk_name[8];
int irq, ret, i = 0;
bool multiplexed_isr = true;
@@ -144,11 +143,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
}
}
- snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
- priv->clk = clk_get(&pdev->dev, clk_name);
+ priv->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
ret = PTR_ERR(priv->clk);
+ dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
goto eclkget;
}
@@ -250,7 +248,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
mmc_hostname(host->mmc), (unsigned long)
(platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
- mmc_data->hclk / 1000000);
+ host->mmc->f_max / 1000000);
return ret;
@@ -330,7 +328,7 @@ static struct platform_driver sh_mobile_sdhi_driver = {
.of_match_table = sh_mobile_sdhi_of_match,
},
.probe = sh_mobile_sdhi_probe,
- .remove = __devexit_p(sh_mobile_sdhi_remove),
+ .remove = sh_mobile_sdhi_remove,
};
module_platform_driver(sh_mobile_sdhi_driver);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 113ce6c9cf32..139212e79cde 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -57,7 +57,7 @@ static int tmio_mmc_resume(struct platform_device *dev)
#define tmio_mmc_resume NULL
#endif
-static int __devinit tmio_mmc_probe(struct platform_device *pdev)
+static int tmio_mmc_probe(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct tmio_mmc_data *pdata;
@@ -107,7 +107,7 @@ out:
return ret;
}
-static int __devexit tmio_mmc_remove(struct platform_device *pdev)
+static int tmio_mmc_remove(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
struct mmc_host *mmc = platform_get_drvdata(pdev);
@@ -133,7 +133,7 @@ static struct platform_driver tmio_mmc_driver = {
.owner = THIS_MODULE,
},
.probe = tmio_mmc_probe,
- .remove = __devexit_p(tmio_mmc_remove),
+ .remove = tmio_mmc_remove,
.suspend = tmio_mmc_suspend,
.resume = tmio_mmc_resume,
};
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 0d8a9bbe30be..50bf495a988b 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -918,7 +918,7 @@ static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
}
-int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+int tmio_mmc_host_probe(struct tmio_mmc_host **host,
struct platform_device *pdev,
struct tmio_mmc_data *pdata)
{
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index f18becef156d..4f84586c6e9e 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -1082,7 +1082,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host)
msleep(1);
}
-static int __devinit via_sd_probe(struct pci_dev *pcidev,
+static int via_sd_probe(struct pci_dev *pcidev,
const struct pci_device_id *id)
{
struct mmc_host *mmc;
@@ -1176,7 +1176,7 @@ disable:
return ret;
}
-static void __devexit via_sd_remove(struct pci_dev *pcidev)
+static void via_sd_remove(struct pci_dev *pcidev)
{
struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev);
unsigned long flags;
@@ -1332,7 +1332,7 @@ static struct pci_driver via_sd_driver = {
.name = DRV_NAME,
.id_table = via_ids,
.probe = via_sd_probe,
- .remove = __devexit_p(via_sd_remove),
+ .remove = via_sd_remove,
.suspend = via_sd_suspend,
.resume = via_sd_resume,
};
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index d5655a63eda4..cb9f361c03ab 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2362,6 +2362,7 @@ error4:
error1:
usb_free_urb(command_out_urb);
error0:
+ usb_put_dev(udev);
return retval;
}
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index 64acd9ce141c..e954b7758876 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1196,7 +1196,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id)
* Allocate/free MMC structure.
*/
-static int __devinit wbsd_alloc_mmc(struct device *dev)
+static int wbsd_alloc_mmc(struct device *dev)
{
struct mmc_host *mmc;
struct wbsd_host *host;
@@ -1288,7 +1288,7 @@ static void wbsd_free_mmc(struct device *dev)
* Scan for known chip id:s
*/
-static int __devinit wbsd_scan(struct wbsd_host *host)
+static int wbsd_scan(struct wbsd_host *host)
{
int i, j, k;
int id;
@@ -1344,7 +1344,7 @@ static int __devinit wbsd_scan(struct wbsd_host *host)
* Allocate/free io port ranges
*/
-static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
+static int wbsd_request_region(struct wbsd_host *host, int base)
{
if (base & 0x7)
return -EINVAL;
@@ -1374,7 +1374,7 @@ static void wbsd_release_regions(struct wbsd_host *host)
* Allocate/free DMA port and buffer
*/
-static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
+static void wbsd_request_dma(struct wbsd_host *host, int dma)
{
if (dma < 0)
return;
@@ -1452,7 +1452,7 @@ static void wbsd_release_dma(struct wbsd_host *host)
* Allocate/free IRQ.
*/
-static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
+static int wbsd_request_irq(struct wbsd_host *host, int irq)
{
int ret;
@@ -1502,7 +1502,7 @@ static void wbsd_release_irq(struct wbsd_host *host)
* Allocate all resources for the host.
*/
-static int __devinit wbsd_request_resources(struct wbsd_host *host,
+static int wbsd_request_resources(struct wbsd_host *host,
int base, int irq, int dma)
{
int ret;
@@ -1644,7 +1644,7 @@ static void wbsd_chip_poweroff(struct wbsd_host *host)
* *
\*****************************************************************************/
-static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
+static int wbsd_init(struct device *dev, int base, int irq, int dma,
int pnp)
{
struct wbsd_host *host = NULL;
@@ -1735,7 +1735,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
return 0;
}
-static void __devexit wbsd_shutdown(struct device *dev, int pnp)
+static void wbsd_shutdown(struct device *dev, int pnp)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
struct wbsd_host *host;
@@ -1762,13 +1762,13 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp)
* Non-PnP
*/
-static int __devinit wbsd_probe(struct platform_device *dev)
+static int wbsd_probe(struct platform_device *dev)
{
/* Use the module parameters for resources */
return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0);
}
-static int __devexit wbsd_remove(struct platform_device *dev)
+static int wbsd_remove(struct platform_device *dev)
{
wbsd_shutdown(&dev->dev, 0);
@@ -1781,7 +1781,7 @@ static int __devexit wbsd_remove(struct platform_device *dev)
#ifdef CONFIG_PNP
-static int __devinit
+static int
wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
{
int io, irq, dma;
@@ -1801,7 +1801,7 @@ wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
}
-static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
+static void wbsd_pnp_remove(struct pnp_dev *dev)
{
wbsd_shutdown(&dev->dev, 1);
}
@@ -1941,7 +1941,7 @@ static struct platform_device *wbsd_device;
static struct platform_driver wbsd_driver = {
.probe = wbsd_probe,
- .remove = __devexit_p(wbsd_remove),
+ .remove = wbsd_remove,
.suspend = wbsd_platform_suspend,
.resume = wbsd_platform_resume,
@@ -1957,7 +1957,7 @@ static struct pnp_driver wbsd_pnp_driver = {
.name = DRIVER_NAME,
.id_table = pnp_dev_table,
.probe = wbsd_pnp_probe,
- .remove = __devexit_p(wbsd_pnp_remove),
+ .remove = wbsd_pnp_remove,
.suspend = wbsd_pnp_suspend,
.resume = wbsd_pnp_resume,
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
new file mode 100644
index 000000000000..5ba4605e4f80
--- /dev/null
+++ b/drivers/mmc/host/wmt-sdmmc.c
@@ -0,0 +1,1029 @@
+/*
+ * WM8505/WM8650 SD/MMC Host Controller
+ *
+ * Copyright (C) 2010 Tony Prisk
+ * Copyright (C) 2008 WonderMedia Technologies, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include <asm/byteorder.h>
+
+
+#define DRIVER_NAME "wmt-sdhc"
+
+
+/* MMC/SD controller registers */
+#define SDMMC_CTLR 0x00
+#define SDMMC_CMD 0x01
+#define SDMMC_RSPTYPE 0x02
+#define SDMMC_ARG 0x04
+#define SDMMC_BUSMODE 0x08
+#define SDMMC_BLKLEN 0x0C
+#define SDMMC_BLKCNT 0x0E
+#define SDMMC_RSP 0x10
+#define SDMMC_CBCR 0x20
+#define SDMMC_INTMASK0 0x24
+#define SDMMC_INTMASK1 0x25
+#define SDMMC_STS0 0x28
+#define SDMMC_STS1 0x29
+#define SDMMC_STS2 0x2A
+#define SDMMC_STS3 0x2B
+#define SDMMC_RSPTIMEOUT 0x2C
+#define SDMMC_CLK 0x30 /* VT8500 only */
+#define SDMMC_EXTCTRL 0x34
+#define SDMMC_SBLKLEN 0x38
+#define SDMMC_DMATIMEOUT 0x3C
+
+
+/* SDMMC_CTLR bit fields */
+#define CTLR_CMD_START 0x01
+#define CTLR_CMD_WRITE 0x04
+#define CTLR_FIFO_RESET 0x08
+
+/* SDMMC_BUSMODE bit fields */
+#define BM_SPI_MODE 0x01
+#define BM_FOURBIT_MODE 0x02
+#define BM_EIGHTBIT_MODE 0x04
+#define BM_SD_OFF 0x10
+#define BM_SPI_CS 0x20
+#define BM_SD_POWER 0x40
+#define BM_SOFT_RESET 0x80
+#define BM_ONEBIT_MASK 0xFD
+
+/* SDMMC_BLKLEN bit fields */
+#define BLKL_CRCERR_ABORT 0x0800
+#define BLKL_CD_POL_HIGH 0x1000
+#define BLKL_GPI_CD 0x2000
+#define BLKL_DATA3_CD 0x4000
+#define BLKL_INT_ENABLE 0x8000
+
+/* SDMMC_INTMASK0 bit fields */
+#define INT0_MBLK_TRAN_DONE_INT_EN 0x10
+#define INT0_BLK_TRAN_DONE_INT_EN 0x20
+#define INT0_CD_INT_EN 0x40
+#define INT0_DI_INT_EN 0x80
+
+/* SDMMC_INTMASK1 bit fields */
+#define INT1_CMD_RES_TRAN_DONE_INT_EN 0x02
+#define INT1_CMD_RES_TOUT_INT_EN 0x04
+#define INT1_MBLK_AUTO_STOP_INT_EN 0x08
+#define INT1_DATA_TOUT_INT_EN 0x10
+#define INT1_RESCRC_ERR_INT_EN 0x20
+#define INT1_RCRC_ERR_INT_EN 0x40
+#define INT1_WCRC_ERR_INT_EN 0x80
+
+/* SDMMC_STS0 bit fields */
+#define STS0_WRITE_PROTECT 0x02
+#define STS0_CD_DATA3 0x04
+#define STS0_CD_GPI 0x08
+#define STS0_MBLK_DONE 0x10
+#define STS0_BLK_DONE 0x20
+#define STS0_CARD_DETECT 0x40
+#define STS0_DEVICE_INS 0x80
+
+/* SDMMC_STS1 bit fields */
+#define STS1_SDIO_INT 0x01
+#define STS1_CMDRSP_DONE 0x02
+#define STS1_RSP_TIMEOUT 0x04
+#define STS1_AUTOSTOP_DONE 0x08
+#define STS1_DATA_TIMEOUT 0x10
+#define STS1_RSP_CRC_ERR 0x20
+#define STS1_RCRC_ERR 0x40
+#define STS1_WCRC_ERR 0x80
+
+/* SDMMC_STS2 bit fields */
+#define STS2_CMD_RES_BUSY 0x10
+#define STS2_DATARSP_BUSY 0x20
+#define STS2_DIS_FORCECLK 0x80
+
+
+/* MMC/SD DMA Controller Registers */
+#define SDDMA_GCR 0x100
+#define SDDMA_IER 0x104
+#define SDDMA_ISR 0x108
+#define SDDMA_DESPR 0x10C
+#define SDDMA_RBR 0x110
+#define SDDMA_DAR 0x114
+#define SDDMA_BAR 0x118
+#define SDDMA_CPR 0x11C
+#define SDDMA_CCR 0x120
+
+
+/* SDDMA_GCR bit fields */
+#define DMA_GCR_DMA_EN 0x00000001
+#define DMA_GCR_SOFT_RESET 0x00000100
+
+/* SDDMA_IER bit fields */
+#define DMA_IER_INT_EN 0x00000001
+
+/* SDDMA_ISR bit fields */
+#define DMA_ISR_INT_STS 0x00000001
+
+/* SDDMA_RBR bit fields */
+#define DMA_RBR_FORMAT 0x40000000
+#define DMA_RBR_END 0x80000000
+
+/* SDDMA_CCR bit fields */
+#define DMA_CCR_RUN 0x00000080
+#define DMA_CCR_IF_TO_PERIPHERAL 0x00000000
+#define DMA_CCR_PERIPHERAL_TO_IF 0x00400000
+
+/* SDDMA_CCR event status */
+#define DMA_CCR_EVT_NO_STATUS 0x00000000
+#define DMA_CCR_EVT_UNDERRUN 0x00000001
+#define DMA_CCR_EVT_OVERRUN 0x00000002
+#define DMA_CCR_EVT_DESP_READ 0x00000003
+#define DMA_CCR_EVT_DATA_RW 0x00000004
+#define DMA_CCR_EVT_EARLY_END 0x00000005
+#define DMA_CCR_EVT_SUCCESS 0x0000000F
+
+#define PDMA_READ 0x00
+#define PDMA_WRITE 0x01
+
+#define WMT_SD_POWER_OFF 0
+#define WMT_SD_POWER_ON 1
+
+struct wmt_dma_descriptor {
+ u32 flags;
+ u32 data_buffer_addr;
+ u32 branch_addr;
+ u32 reserved1;
+};
+
+struct wmt_mci_caps {
+ unsigned int f_min;
+ unsigned int f_max;
+ u32 ocr_avail;
+ u32 caps;
+ u32 max_seg_size;
+ u32 max_segs;
+ u32 max_blk_size;
+};
+
+struct wmt_mci_priv {
+ struct mmc_host *mmc;
+ void __iomem *sdmmc_base;
+
+ int irq_regular;
+ int irq_dma;
+
+ void *dma_desc_buffer;
+ dma_addr_t dma_desc_device_addr;
+
+ struct completion cmdcomp;
+ struct completion datacomp;
+
+ struct completion *comp_cmd;
+ struct completion *comp_dma;
+
+ struct mmc_request *req;
+ struct mmc_command *cmd;
+
+ struct clk *clk_sdmmc;
+ struct device *dev;
+
+ u8 power_inverted;
+ u8 cd_inverted;
+};
+
+static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable)
+{
+ u32 reg_tmp;
+ if (enable) {
+ if (priv->power_inverted) {
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_SD_OFF,
+ priv->sdmmc_base + SDMMC_BUSMODE);
+ } else {
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp & (~BM_SD_OFF),
+ priv->sdmmc_base + SDMMC_BUSMODE);
+ }
+ } else {
+ if (priv->power_inverted) {
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp & (~BM_SD_OFF),
+ priv->sdmmc_base + SDMMC_BUSMODE);
+ } else {
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_SD_OFF,
+ priv->sdmmc_base + SDMMC_BUSMODE);
+ }
+ }
+}
+
+static void wmt_mci_read_response(struct mmc_host *mmc)
+{
+ struct wmt_mci_priv *priv;
+ int idx1, idx2;
+ u8 tmp_resp;
+ u32 response;
+
+ priv = mmc_priv(mmc);
+
+ for (idx1 = 0; idx1 < 4; idx1++) {
+ response = 0;
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if ((idx1 == 3) && (idx2 == 3))
+ tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP);
+ else
+ tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP +
+ (idx1*4) + idx2 + 1);
+ response |= (tmp_resp << (idx2 * 8));
+ }
+ priv->cmd->resp[idx1] = cpu_to_be32(response);
+ }
+}
+
+static void wmt_mci_start_command(struct wmt_mci_priv *priv)
+{
+ u32 reg_tmp;
+
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+ writeb(reg_tmp | CTLR_CMD_START, priv->sdmmc_base + SDMMC_CTLR);
+}
+
+static int wmt_mci_send_command(struct mmc_host *mmc, u8 command, u8 cmdtype,
+ u32 arg, u8 rsptype)
+{
+ struct wmt_mci_priv *priv;
+ u32 reg_tmp;
+
+ priv = mmc_priv(mmc);
+
+ /* write command, arg, resptype registers */
+ writeb(command, priv->sdmmc_base + SDMMC_CMD);
+ writel(arg, priv->sdmmc_base + SDMMC_ARG);
+ writeb(rsptype, priv->sdmmc_base + SDMMC_RSPTYPE);
+
+ /* reset response FIFO */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+ writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+ /* ensure clock enabled - VT3465 */
+ wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+
+ /* clear status bits */
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS2);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS3);
+
+ /* set command type */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+ writeb((reg_tmp & 0x0F) | (cmdtype << 4),
+ priv->sdmmc_base + SDMMC_CTLR);
+
+ return 0;
+}
+
+static void wmt_mci_disable_dma(struct wmt_mci_priv *priv)
+{
+ writel(DMA_ISR_INT_STS, priv->sdmmc_base + SDDMA_ISR);
+ writel(0, priv->sdmmc_base + SDDMA_IER);
+}
+
+static void wmt_complete_data_request(struct wmt_mci_priv *priv)
+{
+ struct mmc_request *req;
+ req = priv->req;
+
+ req->data->bytes_xfered = req->data->blksz * req->data->blocks;
+
+ /* unmap the DMA pages used for write data */
+ if (req->data->flags & MMC_DATA_WRITE)
+ dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+ req->data->sg_len, DMA_TO_DEVICE);
+ else
+ dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+ req->data->sg_len, DMA_FROM_DEVICE);
+
+ /* Check if the DMA ISR returned a data error */
+ if ((req->cmd->error) || (req->data->error))
+ mmc_request_done(priv->mmc, req);
+ else {
+ wmt_mci_read_response(priv->mmc);
+ if (!req->data->stop) {
+ /* single-block read/write requests end here */
+ mmc_request_done(priv->mmc, req);
+ } else {
+ /*
+ * we change the priv->cmd variable so the response is
+ * stored in the stop struct rather than the original
+ * calling command struct
+ */
+ priv->comp_cmd = &priv->cmdcomp;
+ init_completion(priv->comp_cmd);
+ priv->cmd = req->data->stop;
+ wmt_mci_send_command(priv->mmc, req->data->stop->opcode,
+ 7, req->data->stop->arg, 9);
+ wmt_mci_start_command(priv);
+ }
+ }
+}
+
+static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data)
+{
+ struct mmc_host *mmc;
+ struct wmt_mci_priv *priv;
+
+ int status;
+
+ priv = (struct wmt_mci_priv *)data;
+ mmc = priv->mmc;
+
+ status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F;
+
+ if (status != DMA_CCR_EVT_SUCCESS) {
+ dev_err(priv->dev, "DMA Error: Status = %d\n", status);
+ priv->req->data->error = -ETIMEDOUT;
+ complete(priv->comp_dma);
+ return IRQ_HANDLED;
+ }
+
+ priv->req->data->error = 0;
+
+ wmt_mci_disable_dma(priv);
+
+ complete(priv->comp_dma);
+
+ if (priv->comp_cmd) {
+ if (completion_done(priv->comp_cmd)) {
+ /*
+ * if the command (regular) interrupt has already
+ * completed, finish off the request otherwise we wait
+ * for the command interrupt and finish from there.
+ */
+ wmt_complete_data_request(priv);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wmt_mci_regular_isr(int irq_num, void *data)
+{
+ struct wmt_mci_priv *priv;
+ u32 status0;
+ u32 status1;
+ u32 status2;
+ u32 reg_tmp;
+ int cmd_done;
+
+ priv = (struct wmt_mci_priv *)data;
+ cmd_done = 0;
+ status0 = readb(priv->sdmmc_base + SDMMC_STS0);
+ status1 = readb(priv->sdmmc_base + SDMMC_STS1);
+ status2 = readb(priv->sdmmc_base + SDMMC_STS2);
+
+ /* Check for card insertion */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+ if ((reg_tmp & INT0_DI_INT_EN) && (status0 & STS0_DEVICE_INS)) {
+ mmc_detect_change(priv->mmc, 0);
+ if (priv->cmd)
+ priv->cmd->error = -ETIMEDOUT;
+ if (priv->comp_cmd)
+ complete(priv->comp_cmd);
+ if (priv->comp_dma) {
+ wmt_mci_disable_dma(priv);
+ complete(priv->comp_dma);
+ }
+ writeb(STS0_DEVICE_INS, priv->sdmmc_base + SDMMC_STS0);
+ return IRQ_HANDLED;
+ }
+
+ if ((!priv->req->data) ||
+ ((priv->req->data->stop) && (priv->cmd == priv->req->data->stop))) {
+ /* handle non-data & stop_transmission requests */
+ if (status1 & STS1_CMDRSP_DONE) {
+ priv->cmd->error = 0;
+ cmd_done = 1;
+ } else if ((status1 & STS1_RSP_TIMEOUT) ||
+ (status1 & STS1_DATA_TIMEOUT)) {
+ priv->cmd->error = -ETIMEDOUT;
+ cmd_done = 1;
+ }
+
+ if (cmd_done) {
+ priv->comp_cmd = NULL;
+
+ if (!priv->cmd->error)
+ wmt_mci_read_response(priv->mmc);
+
+ priv->cmd = NULL;
+
+ mmc_request_done(priv->mmc, priv->req);
+ }
+ } else {
+ /* handle data requests */
+ if (status1 & STS1_CMDRSP_DONE) {
+ if (priv->cmd)
+ priv->cmd->error = 0;
+ if (priv->comp_cmd)
+ complete(priv->comp_cmd);
+ }
+
+ if ((status1 & STS1_RSP_TIMEOUT) ||
+ (status1 & STS1_DATA_TIMEOUT)) {
+ if (priv->cmd)
+ priv->cmd->error = -ETIMEDOUT;
+ if (priv->comp_cmd)
+ complete(priv->comp_cmd);
+ if (priv->comp_dma) {
+ wmt_mci_disable_dma(priv);
+ complete(priv->comp_dma);
+ }
+ }
+
+ if (priv->comp_dma) {
+ /*
+ * If the dma interrupt has already completed, finish
+ * off the request; otherwise we wait for the DMA
+ * interrupt and finish from there.
+ */
+ if (completion_done(priv->comp_dma))
+ wmt_complete_data_request(priv);
+ }
+ }
+
+ writeb(status0, priv->sdmmc_base + SDMMC_STS0);
+ writeb(status1, priv->sdmmc_base + SDMMC_STS1);
+ writeb(status2, priv->sdmmc_base + SDMMC_STS2);
+
+ return IRQ_HANDLED;
+}
+
+static void wmt_reset_hardware(struct mmc_host *mmc)
+{
+ struct wmt_mci_priv *priv;
+ u32 reg_tmp;
+
+ priv = mmc_priv(mmc);
+
+ /* reset controller */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+
+ /* reset response FIFO */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+ writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+ /* enable GPI pin to detect card */
+ writew(BLKL_INT_ENABLE | BLKL_GPI_CD, priv->sdmmc_base + SDMMC_BLKLEN);
+
+ /* clear interrupt status */
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+ /* setup interrupts */
+ writeb(INT0_CD_INT_EN | INT0_DI_INT_EN, priv->sdmmc_base +
+ SDMMC_INTMASK0);
+ writeb(INT1_DATA_TOUT_INT_EN | INT1_CMD_RES_TRAN_DONE_INT_EN |
+ INT1_CMD_RES_TOUT_INT_EN, priv->sdmmc_base + SDMMC_INTMASK1);
+
+ /* set the DMA timeout */
+ writew(8191, priv->sdmmc_base + SDMMC_DMATIMEOUT);
+
+ /* auto clock freezing enable */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_STS2);
+ writeb(reg_tmp | STS2_DIS_FORCECLK, priv->sdmmc_base + SDMMC_STS2);
+
+ /* set a default clock speed of 400Khz */
+ clk_set_rate(priv->clk_sdmmc, 400000);
+}
+
+static int wmt_dma_init(struct mmc_host *mmc)
+{
+ struct wmt_mci_priv *priv;
+
+ priv = mmc_priv(mmc);
+
+ writel(DMA_GCR_SOFT_RESET, priv->sdmmc_base + SDDMA_GCR);
+ writel(DMA_GCR_DMA_EN, priv->sdmmc_base + SDDMA_GCR);
+ if ((readl(priv->sdmmc_base + SDDMA_GCR) & DMA_GCR_DMA_EN) != 0)
+ return 0;
+ else
+ return 1;
+}
+
+static void wmt_dma_init_descriptor(struct wmt_dma_descriptor *desc,
+ u16 req_count, u32 buffer_addr, u32 branch_addr, int end)
+{
+ desc->flags = 0x40000000 | req_count;
+ if (end)
+ desc->flags |= 0x80000000;
+ desc->data_buffer_addr = buffer_addr;
+ desc->branch_addr = branch_addr;
+}
+
+static void wmt_dma_config(struct mmc_host *mmc, u32 descaddr, u8 dir)
+{
+ struct wmt_mci_priv *priv;
+ u32 reg_tmp;
+
+ priv = mmc_priv(mmc);
+
+ /* Enable DMA Interrupts */
+ writel(DMA_IER_INT_EN, priv->sdmmc_base + SDDMA_IER);
+
+ /* Write DMA Descriptor Pointer Register */
+ writel(descaddr, priv->sdmmc_base + SDDMA_DESPR);
+
+ writel(0x00, priv->sdmmc_base + SDDMA_CCR);
+
+ if (dir == PDMA_WRITE) {
+ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+ writel(reg_tmp & DMA_CCR_IF_TO_PERIPHERAL, priv->sdmmc_base +
+ SDDMA_CCR);
+ } else {
+ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+ writel(reg_tmp | DMA_CCR_PERIPHERAL_TO_IF, priv->sdmmc_base +
+ SDDMA_CCR);
+ }
+}
+
+static void wmt_dma_start(struct wmt_mci_priv *priv)
+{
+ u32 reg_tmp;
+
+ reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+ writel(reg_tmp | DMA_CCR_RUN, priv->sdmmc_base + SDDMA_CCR);
+}
+
+static void wmt_mci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct wmt_mci_priv *priv;
+ struct wmt_dma_descriptor *desc;
+ u8 command;
+ u8 cmdtype;
+ u32 arg;
+ u8 rsptype;
+ u32 reg_tmp;
+
+ struct scatterlist *sg;
+ int i;
+ int sg_cnt;
+ int offset;
+ u32 dma_address;
+ int desc_cnt;
+
+ priv = mmc_priv(mmc);
+ priv->req = req;
+
+ /*
+ * Use the cmd variable to pass a pointer to the resp[] structure
+ * This is required on multi-block requests to pass the pointer to the
+ * stop command
+ */
+ priv->cmd = req->cmd;
+
+ command = req->cmd->opcode;
+ arg = req->cmd->arg;
+ rsptype = mmc_resp_type(req->cmd);
+ cmdtype = 0;
+
+ /* rsptype=7 only valid for SPI commands - should be =2 for SD */
+ if (rsptype == 7)
+ rsptype = 2;
+ /* rsptype=21 is R1B, convert for controller */
+ if (rsptype == 21)
+ rsptype = 9;
+
+ if (!req->data) {
+ wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+ wmt_mci_start_command(priv);
+ /* completion is now handled in the regular_isr() */
+ }
+ if (req->data) {
+ priv->comp_cmd = &priv->cmdcomp;
+ init_completion(priv->comp_cmd);
+
+ wmt_dma_init(mmc);
+
+ /* set controller data length */
+ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+ writew((reg_tmp & 0xF800) | (req->data->blksz - 1),
+ priv->sdmmc_base + SDMMC_BLKLEN);
+
+ /* set controller block count */
+ writew(req->data->blocks, priv->sdmmc_base + SDMMC_BLKCNT);
+
+ desc = (struct wmt_dma_descriptor *)priv->dma_desc_buffer;
+
+ if (req->data->flags & MMC_DATA_WRITE) {
+ sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+ req->data->sg_len, DMA_TO_DEVICE);
+ cmdtype = 1;
+ if (req->data->blocks > 1)
+ cmdtype = 3;
+ } else {
+ sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+ req->data->sg_len, DMA_FROM_DEVICE);
+ cmdtype = 2;
+ if (req->data->blocks > 1)
+ cmdtype = 4;
+ }
+
+ dma_address = priv->dma_desc_device_addr + 16;
+ desc_cnt = 0;
+
+ for_each_sg(req->data->sg, sg, sg_cnt, i) {
+ offset = 0;
+ while (offset < sg_dma_len(sg)) {
+ wmt_dma_init_descriptor(desc, req->data->blksz,
+ sg_dma_address(sg)+offset,
+ dma_address, 0);
+ desc++;
+ desc_cnt++;
+ offset += req->data->blksz;
+ dma_address += 16;
+ if (desc_cnt == req->data->blocks)
+ break;
+ }
+ }
+ desc--;
+ desc->flags |= 0x80000000;
+
+ if (req->data->flags & MMC_DATA_WRITE)
+ wmt_dma_config(mmc, priv->dma_desc_device_addr,
+ PDMA_WRITE);
+ else
+ wmt_dma_config(mmc, priv->dma_desc_device_addr,
+ PDMA_READ);
+
+ wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+
+ priv->comp_dma = &priv->datacomp;
+ init_completion(priv->comp_dma);
+
+ wmt_dma_start(priv);
+ wmt_mci_start_command(priv);
+ }
+}
+
+static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct wmt_mci_priv *priv;
+ u32 reg_tmp;
+
+ priv = mmc_priv(mmc);
+
+ if (ios->power_mode == MMC_POWER_UP) {
+ wmt_reset_hardware(mmc);
+
+ wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+ }
+ if (ios->power_mode == MMC_POWER_OFF)
+ wmt_set_sd_power(priv, WMT_SD_POWER_OFF);
+
+ if (ios->clock != 0)
+ clk_set_rate(priv->clk_sdmmc, ios->clock);
+
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+ writeb(reg_tmp | 0x04, priv->sdmmc_base + SDMMC_EXTCTRL);
+ break;
+ case MMC_BUS_WIDTH_4:
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_FOURBIT_MODE, priv->sdmmc_base +
+ SDMMC_BUSMODE);
+
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+ writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+ break;
+ case MMC_BUS_WIDTH_1:
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp & BM_ONEBIT_MASK, priv->sdmmc_base +
+ SDMMC_BUSMODE);
+
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+ writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+ break;
+ }
+}
+
+static int wmt_mci_get_ro(struct mmc_host *mmc)
+{
+ struct wmt_mci_priv *priv = mmc_priv(mmc);
+
+ return !(readb(priv->sdmmc_base + SDMMC_STS0) & STS0_WRITE_PROTECT);
+}
+
+static int wmt_mci_get_cd(struct mmc_host *mmc)
+{
+ struct wmt_mci_priv *priv = mmc_priv(mmc);
+ u32 cd = (readb(priv->sdmmc_base + SDMMC_STS0) & STS0_CD_GPI) >> 3;
+
+ return !(cd ^ priv->cd_inverted);
+}
+
+static struct mmc_host_ops wmt_mci_ops = {
+ .request = wmt_mci_request,
+ .set_ios = wmt_mci_set_ios,
+ .get_ro = wmt_mci_get_ro,
+ .get_cd = wmt_mci_get_cd,
+};
+
+/* Controller capabilities */
+static struct wmt_mci_caps wm8505_caps = {
+ .f_min = 390425,
+ .f_max = 50000000,
+ .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_SD_HIGHSPEED,
+ .max_seg_size = 65024,
+ .max_segs = 128,
+ .max_blk_size = 2048,
+};
+
+static struct of_device_id wmt_mci_dt_ids[] = {
+ { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps },
+ { /* Sentinel */ },
+};
+
+static int __devinit wmt_mci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct wmt_mci_priv *priv;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id =
+ of_match_device(wmt_mci_dt_ids, &pdev->dev);
+ const struct wmt_mci_caps *wmt_caps = of_id->data;
+ int ret;
+ int regular_irq, dma_irq;
+
+ if (!of_id || !of_id->data) {
+ dev_err(&pdev->dev, "Controller capabilities data missing\n");
+ return -EFAULT;
+ }
+
+ if (!np) {
+ dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n");
+ return -EFAULT;
+ }
+
+ regular_irq = irq_of_parse_and_map(np, 0);
+ dma_irq = irq_of_parse_and_map(np, 1);
+
+ if (!regular_irq || !dma_irq) {
+ dev_err(&pdev->dev, "Getting IRQs failed!\n");
+ ret = -ENXIO;
+ goto fail1;
+ }
+
+ mmc = mmc_alloc_host(sizeof(struct wmt_mci_priv), &pdev->dev);
+ if (!mmc) {
+ dev_err(&pdev->dev, "Failed to allocate mmc_host\n");
+ ret = -ENOMEM;
+ goto fail1;
+ }
+
+ mmc->ops = &wmt_mci_ops;
+ mmc->f_min = wmt_caps->f_min;
+ mmc->f_max = wmt_caps->f_max;
+ mmc->ocr_avail = wmt_caps->ocr_avail;
+ mmc->caps = wmt_caps->caps;
+
+ mmc->max_seg_size = wmt_caps->max_seg_size;
+ mmc->max_segs = wmt_caps->max_segs;
+ mmc->max_blk_size = wmt_caps->max_blk_size;
+
+ mmc->max_req_size = (16*512*mmc->max_segs);
+ mmc->max_blk_count = mmc->max_req_size / 512;
+
+ priv = mmc_priv(mmc);
+ priv->mmc = mmc;
+ priv->dev = &pdev->dev;
+
+ priv->power_inverted = 0;
+ priv->cd_inverted = 0;
+
+ if (of_get_property(np, "sdon-inverted", NULL))
+ priv->power_inverted = 1;
+ if (of_get_property(np, "cd-inverted", NULL))
+ priv->cd_inverted = 1;
+
+ priv->sdmmc_base = of_iomap(np, 0);
+ if (!priv->sdmmc_base) {
+ dev_err(&pdev->dev, "Failed to map IO space\n");
+ ret = -ENOMEM;
+ goto fail2;
+ }
+
+ priv->irq_regular = regular_irq;
+ priv->irq_dma = dma_irq;
+
+ ret = request_irq(regular_irq, wmt_mci_regular_isr, 0, "sdmmc", priv);
+ if (ret) {
+ dev_err(&pdev->dev, "Register regular IRQ fail\n");
+ goto fail3;
+ }
+
+ ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv);
+ if (ret) {
+ dev_err(&pdev->dev, "Register DMA IRQ fail\n");
+ goto fail4;
+ }
+
+ /* alloc some DMA buffers for descriptors/transfers */
+ priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev,
+ mmc->max_blk_count * 16,
+ &priv->dma_desc_device_addr,
+ 208);
+ if (!priv->dma_desc_buffer) {
+ dev_err(&pdev->dev, "DMA alloc fail\n");
+ ret = -EPERM;
+ goto fail5;
+ }
+
+ platform_set_drvdata(pdev, mmc);
+
+ priv->clk_sdmmc = of_clk_get(np, 0);
+ if (IS_ERR(priv->clk_sdmmc)) {
+ dev_err(&pdev->dev, "Error getting clock\n");
+ ret = PTR_ERR(priv->clk_sdmmc);
+ goto fail5;
+ }
+
+ clk_prepare_enable(priv->clk_sdmmc);
+
+ /* configure the controller to a known 'ready' state */
+ wmt_reset_hardware(mmc);
+
+ mmc_add_host(mmc);
+
+ dev_info(&pdev->dev, "WMT SDHC Controller initialized\n");
+
+ return 0;
+fail5:
+ free_irq(dma_irq, priv);
+fail4:
+ free_irq(regular_irq, priv);
+fail3:
+ iounmap(priv->sdmmc_base);
+fail2:
+ mmc_free_host(mmc);
+fail1:
+ return ret;
+}
+
+static int __devexit wmt_mci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct wmt_mci_priv *priv;
+ struct resource *res;
+ u32 reg_tmp;
+
+ mmc = platform_get_drvdata(pdev);
+ priv = mmc_priv(mmc);
+
+ /* reset SD controller */
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writel(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+ writew(reg_tmp & ~(0xA000), priv->sdmmc_base + SDMMC_BLKLEN);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+ /* release the dma buffers */
+ dma_free_coherent(&pdev->dev, priv->mmc->max_blk_count * 16,
+ priv->dma_desc_buffer, priv->dma_desc_device_addr);
+
+ mmc_remove_host(mmc);
+
+ free_irq(priv->irq_regular, priv);
+ free_irq(priv->irq_dma, priv);
+
+ iounmap(priv->sdmmc_base);
+
+ clk_disable_unprepare(priv->clk_sdmmc);
+ clk_put(priv->clk_sdmmc);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ mmc_free_host(mmc);
+
+ platform_set_drvdata(pdev, NULL);
+
+ dev_info(&pdev->dev, "WMT MCI device removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int wmt_mci_suspend(struct device *dev)
+{
+ u32 reg_tmp;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct wmt_mci_priv *priv;
+ int ret;
+
+ if (!mmc)
+ return 0;
+
+ priv = mmc_priv(mmc);
+ ret = mmc_suspend_host(mmc);
+
+ if (!ret) {
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+ SDMMC_BUSMODE);
+
+ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+ writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN);
+
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+ writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+ clk_disable(priv->clk_sdmmc);
+ }
+ return ret;
+}
+
+static int wmt_mci_resume(struct device *dev)
+{
+ u32 reg_tmp;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct wmt_mci_priv *priv;
+ int ret = 0;
+
+ if (mmc) {
+ priv = mmc_priv(mmc);
+ clk_enable(priv->clk_sdmmc);
+
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+ writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+ SDMMC_BUSMODE);
+
+ reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+ writew(reg_tmp | (BLKL_GPI_CD | BLKL_INT_ENABLE),
+ priv->sdmmc_base + SDMMC_BLKLEN);
+
+ reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+ writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base +
+ SDMMC_INTMASK0);
+
+ ret = mmc_resume_host(mmc);
+ }
+
+ return ret;
+}
+
+static const struct dev_pm_ops wmt_mci_pm = {
+ .suspend = wmt_mci_suspend,
+ .resume = wmt_mci_resume,
+};
+
+#define wmt_mci_pm_ops (&wmt_mci_pm)
+
+#else /* !CONFIG_PM */
+
+#define wmt_mci_pm_ops NULL
+
+#endif
+
+static struct platform_driver wmt_mci_driver = {
+ .probe = wmt_mci_probe,
+ .remove = __exit_p(wmt_mci_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = wmt_mci_pm_ops,
+ .of_match_table = wmt_mci_dt_ids,
+ },
+};
+
+module_platform_driver(wmt_mci_driver);
+
+MODULE_DESCRIPTION("Wondermedia MMC/SD Driver");
+MODULE_AUTHOR("Tony Prisk");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids);
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 8f52fc858e48..5a5cd2ace4a6 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
if (*(szlength) != '+') {
devlength = simple_strtoul(szlength, &buffer, 0);
- devlength = handle_unit(devlength, buffer) - devstart;
+ devlength = handle_unit(devlength, buffer);
if (devlength < devstart)
goto err_out;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 374c46dff7dd..ec794a72975d 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1077,7 +1077,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
* until the request succeeds or until the allocation size falls below
* the system page size. This attempts to make sure it does not adversely
* impact system performance, so when allocating more than one page, we
- * ask the memory allocator to avoid re-trying.
+ * ask the memory allocator to avoid re-trying, swapping, writing back
+ * or performing I/O.
*
* Note, this function also makes sure that the allocated buffer is aligned to
* the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
@@ -1091,7 +1092,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
*/
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
{
- gfp_t flags = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY;
+ gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
+ __GFP_NORETRY | __GFP_NO_KSWAPD;
size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
void *kbuf;
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 914455783302..92623ac2015a 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -41,6 +41,7 @@
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/platform_data/atmel.h>
+#include <linux/pinctrl/consumer.h>
#include <mach/cpu.h>
@@ -1370,6 +1371,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
struct resource *mem;
struct mtd_part_parser_data ppdata = {};
int res;
+ struct pinctrl *pinctrl;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
@@ -1414,6 +1416,13 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
nand_chip->IO_ADDR_W = host->io_base;
nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(host->dev, "Failed to request pinctrl\n");
+ res = PTR_ERR(pinctrl);
+ goto err_ecc_ioremap;
+ }
+
if (gpio_is_valid(host->board.rdy_pin)) {
res = gpio_request(host->board.rdy_pin, "nand_rdy");
if (res < 0) {
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ec6841d8e956..1a03b7f673ce 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
/*
* Field definitions are in the following datasheets:
* Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
- * New style (6 byte ID): Samsung K9GAG08U0F (p.44)
+ * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
* Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22)
*
- * Check for ID length, cell type, and Hynix/Samsung ID to decide what
- * to do.
+ * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
+ * ID to decide what to do.
*/
- if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+ if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
+ (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+ id_data[5] != 0x00) {
/* Calc pagesize */
mtd->writesize = 2048 << (extid & 0x03);
extid >>= 2;
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 4fbfe96e37a1..f48ac5d80bbf 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -727,7 +727,9 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
if (!flctl->qos_request) {
ret = dev_pm_qos_add_request(&flctl->pdev->dev,
- &flctl->pm_qos, 100);
+ &flctl->pm_qos,
+ DEV_PM_QOS_LATENCY,
+ 100);
if (ret < 0)
dev_err(&flctl->pdev->dev,
"PM QoS request failed: %d\n", ret);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 64be8f0848b0..d9127e2ed808 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
nr_parts = plen / sizeof(part[0]);
*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
- if (!pparts)
+ if (!*pparts)
return -ENOMEM;
names = of_get_property(dp, "partition-names", &plen);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 7153e0d27101..b3f41f200622 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
* flexonenand_set_boundary - Writes the SLC boundary
* @param mtd - mtd info structure
*/
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
int boundary, int lock)
{
struct onenand_chip *this = mtd->priv;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index da7b44998b40..2144f611196e 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -498,7 +498,7 @@ out:
* @ubi: UBI device description object
*
* This function returns a physical eraseblock in case of success and a
- * negative error code in case of failure. Might sleep.
+ * negative error code in case of failure.
*/
static int __wl_get_peb(struct ubi_device *ubi)
{
@@ -540,13 +540,6 @@ retry:
* ubi_wl_get_peb() after removing e from the pool. */
prot_queue_add(ubi, e);
#endif
- 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;
- }
-
return e->pnum;
}
@@ -679,17 +672,30 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
#else
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
{
- return find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+ struct ubi_wl_entry *e;
+
+ e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+ self_check_in_wl_tree(ubi, e, &ubi->free);
+ rb_erase(&e->u.rb, &ubi->free);
+
+ return e;
}
int ubi_wl_get_peb(struct ubi_device *ubi)
{
- int peb;
+ int peb, err;
spin_lock(&ubi->wl_lock);
peb = __wl_get_peb(ubi);
spin_unlock(&ubi->wl_lock);
+ err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset,
+ ubi->peb_size - ubi->vid_hdr_aloffset);
+ if (err) {
+ ubi_err("new PEB %d does not contain all 0xFF bytes", peb);
+ return err;
+ }
+
return peb;
}
#endif
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b2530b002125..a7d47350ea4b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond)
struct net_device *bond_dev = bond->dev;
netdev_features_t vlan_features = BOND_VLAN_FEATURES;
unsigned short max_hard_header_len = ETH_HLEN;
+ unsigned int gso_max_size = GSO_MAX_SIZE;
+ u16 gso_max_segs = GSO_MAX_SEGS;
int i;
unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
@@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond)
dst_release_flag &= slave->dev->priv_flags;
if (slave->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = slave->dev->hard_header_len;
+
+ gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+ gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
}
done:
bond_dev->vlan_features = vlan_features;
bond_dev->hard_header_len = max_hard_header_len;
+ bond_dev->gso_max_segs = gso_max_segs;
+ netif_set_gso_max_size(bond_dev, gso_max_size);
flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
bond_dev->priv_flags = flags | dst_release_flag;
@@ -3452,6 +3459,28 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
/*-------------------------- Device entry points ----------------------------*/
+static void bond_work_init_all(struct bonding *bond)
+{
+ INIT_DELAYED_WORK(&bond->mcast_work,
+ bond_resend_igmp_join_requests_delayed);
+ INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+ INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon);
+ else
+ INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
+ INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+}
+
+static void bond_work_cancel_all(struct bonding *bond)
+{
+ cancel_delayed_work_sync(&bond->mii_work);
+ cancel_delayed_work_sync(&bond->arp_work);
+ cancel_delayed_work_sync(&bond->alb_work);
+ cancel_delayed_work_sync(&bond->ad_work);
+ cancel_delayed_work_sync(&bond->mcast_work);
+}
+
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
@@ -3474,41 +3503,27 @@ static int bond_open(struct net_device *bond_dev)
}
read_unlock(&bond->lock);
- INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+ bond_work_init_all(bond);
if (bond_is_lb(bond)) {
/* bond_alb_initialize must be called before the timer
* is started.
*/
- if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
- /* something went wrong - fail the open operation */
+ if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
return -ENOMEM;
- }
-
- INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
queue_delayed_work(bond->wq, &bond->alb_work, 0);
}
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+ if (bond->params.miimon) /* link check interval, in milliseconds. */
queue_delayed_work(bond->wq, &bond->mii_work, 0);
- }
if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
queue_delayed_work(bond->wq, &bond->arp_work, 0);
if (bond->params.arp_validate)
bond->recv_probe = bond_arp_rcv;
}
if (bond->params.mode == BOND_MODE_8023AD) {
- INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond->recv_probe = bond_3ad_lacpdu_recv;
@@ -3523,34 +3538,10 @@ static int bond_close(struct net_device *bond_dev)
struct bonding *bond = netdev_priv(bond_dev);
write_lock_bh(&bond->lock);
-
bond->send_peer_notif = 0;
-
write_unlock_bh(&bond->lock);
- if (bond->params.miimon) { /* link check interval, in milliseconds. */
- cancel_delayed_work_sync(&bond->mii_work);
- }
-
- if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
- cancel_delayed_work_sync(&bond->arp_work);
- }
-
- switch (bond->params.mode) {
- case BOND_MODE_8023AD:
- cancel_delayed_work_sync(&bond->ad_work);
- break;
- case BOND_MODE_TLB:
- case BOND_MODE_ALB:
- cancel_delayed_work_sync(&bond->alb_work);
- break;
- default:
- break;
- }
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work_sync(&bond->mcast_work);
-
+ bond_work_cancel_all(bond);
if (bond_is_lb(bond)) {
/* Must be called only after all
* slaves have been released
@@ -4429,26 +4420,6 @@ static void bond_setup(struct net_device *bond_dev)
bond_dev->features |= bond_dev->hw_features;
}
-static void bond_work_cancel_all(struct bonding *bond)
-{
- if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
- cancel_delayed_work_sync(&bond->mii_work);
-
- if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
- cancel_delayed_work_sync(&bond->arp_work);
-
- if (bond->params.mode == BOND_MODE_ALB &&
- delayed_work_pending(&bond->alb_work))
- cancel_delayed_work_sync(&bond->alb_work);
-
- if (bond->params.mode == BOND_MODE_8023AD &&
- delayed_work_pending(&bond->ad_work))
- cancel_delayed_work_sync(&bond->ad_work);
-
- if (delayed_work_pending(&bond->mcast_work))
- cancel_delayed_work_sync(&bond->mcast_work);
-}
-
/*
* Destroy a bonding device.
* Must be under rtnl_lock when this function is called.
@@ -4699,12 +4670,13 @@ static int bond_check_params(struct bond_params *params)
arp_ip_count++) {
/* not complete check, but should be good enough to
catch mistakes */
- if (!isdigit(arp_ip_target[arp_ip_count][0])) {
+ __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
+ if (!isdigit(arp_ip_target[arp_ip_count][0]) ||
+ ip == 0 || ip == htonl(INADDR_BROADCAST)) {
pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
arp_ip_target[arp_ip_count]);
arp_interval = 0;
} else {
- __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
arp_target[arp_ip_count] = ip;
}
}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index ef8d2a080d17..1877ed7ca086 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -513,6 +513,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no arp_interval value specified.\n",
bond->dev->name);
@@ -539,10 +541,6 @@ static ssize_t bonding_store_arp_interval(struct device *d,
pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
bond->dev->name, bond->dev->name);
bond->params.miimon = 0;
- if (delayed_work_pending(&bond->mii_work)) {
- cancel_delayed_work(&bond->mii_work);
- flush_workqueue(bond->wq);
- }
}
if (!bond->params.arp_targets[0]) {
pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
@@ -554,19 +552,12 @@ static ssize_t bonding_store_arp_interval(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (!delayed_work_pending(&bond->arp_work)) {
- if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_activebackup_arp_mon);
- else
- INIT_DELAYED_WORK(&bond->arp_work,
- bond_loadbalance_arp_mon);
-
- queue_delayed_work(bond->wq, &bond->arp_work, 0);
- }
+ cancel_delayed_work_sync(&bond->mii_work);
+ queue_delayed_work(bond->wq, &bond->arp_work, 0);
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
@@ -962,6 +953,8 @@ static ssize_t bonding_store_miimon(struct device *d,
int new_value, ret = count;
struct bonding *bond = to_bond(d);
+ if (!rtnl_trylock())
+ return restart_syscall();
if (sscanf(buf, "%d", &new_value) != 1) {
pr_err("%s: no miimon value specified.\n",
bond->dev->name);
@@ -993,10 +986,6 @@ static ssize_t bonding_store_miimon(struct device *d,
bond->params.arp_validate =
BOND_ARP_VALIDATE_NONE;
}
- if (delayed_work_pending(&bond->arp_work)) {
- cancel_delayed_work(&bond->arp_work);
- flush_workqueue(bond->wq);
- }
}
if (bond->dev->flags & IFF_UP) {
@@ -1005,15 +994,12 @@ static ssize_t bonding_store_miimon(struct device *d,
* timer will get fired off when the open function
* is called.
*/
- if (!delayed_work_pending(&bond->mii_work)) {
- INIT_DELAYED_WORK(&bond->mii_work,
- bond_mii_monitor);
- queue_delayed_work(bond->wq,
- &bond->mii_work, 0);
- }
+ cancel_delayed_work_sync(&bond->arp_work);
+ queue_delayed_work(bond->wq, &bond->mii_work, 0);
}
}
out:
+ rtnl_unlock();
return ret;
}
static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
@@ -1582,6 +1568,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
goto out;
}
+ read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (!bond_is_active_slave(slave)) {
if (new_value)
@@ -1590,6 +1577,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
slave->inactive = 1;
}
}
+ read_unlock(&bond->lock);
out:
return ret;
}
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index 86f26a1ede4c..25723d8ee201 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
mc->pdev->dev.can.state = new_state;
if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
+ struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
+
peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
- skb->tstamp = timeval_to_ktime(tv);
+ hwts->hwtstamp = timeval_to_ktime(tv);
}
netif_rx(skb);
@@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
struct sk_buff *skb;
struct can_frame *cf;
struct timeval tv;
+ struct skb_shared_hwtstamps *hwts;
skb = alloc_can_skb(mc->netdev, &cf);
if (!skb)
@@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
/* convert timestamp into kernel time */
peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
- skb->tstamp = timeval_to_ktime(tv);
+ hwts = skb_hwtstamps(skb);
+ hwts->hwtstamp = timeval_to_ktime(tv);
/* push the skb */
netif_rx(skb);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index e1626d92511a..30d79bfa5b10 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
struct can_frame *can_frame;
struct sk_buff *skb;
struct timeval tv;
+ struct skb_shared_hwtstamps *hwts;
skb = alloc_can_skb(netdev, &can_frame);
if (!skb)
@@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
memcpy(can_frame->data, rx->data, can_frame->can_dlc);
peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv);
- skb->tstamp = timeval_to_ktime(tv);
+ hwts = skb_hwtstamps(skb);
+ hwts->hwtstamp = timeval_to_ktime(tv);
netif_rx(skb);
netdev->stats.rx_packets++;
@@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
u8 err_mask = 0;
struct sk_buff *skb;
struct timeval tv;
+ struct skb_shared_hwtstamps *hwts;
/* nothing should be sent while in BUS_OFF state */
if (dev->can.state == CAN_STATE_BUS_OFF)
@@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
dev->can.state = new_state;
peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv);
- skb->tstamp = timeval_to_ktime(tv);
+ hwts = skb_hwtstamps(skb);
+ hwts->hwtstamp = timeval_to_ktime(tv);
netif_rx(skb);
netdev->stats.rx_packets++;
netdev->stats.rx_bytes += can_frame->can_dlc;
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
index d04911d33b64..47618e505355 100644
--- a/drivers/net/ethernet/8390/ne.c
+++ b/drivers/net/ethernet/8390/ne.c
@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev)
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
}
+ SET_NETDEV_DEV(dev, &pdev->dev);
err = do_ne_probe(dev);
if (err) {
free_netdev(dev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index bd1fd3d87c24..01611b33a93d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9545,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
*/
static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
{
- u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
- if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
- BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
- REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+ if (!CHIP_IS_E1x(bp)) {
+ u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+ if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+ BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+ REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR,
+ 1 << BP_FUNC(bp));
+ }
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
index 5d36795877cb..b799ab12a291 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
@@ -237,7 +237,7 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
if (err)
return err;
- memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate));
+ memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));
return 0;
}
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index 1c818254b7be..609125a249d9 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp)
cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
- cpw32_f(HiTxRingAddr, 0);
- cpw32_f(HiTxRingAddr + 4, 0);
-
- ring_dma = cp->ring_dma;
- cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
- ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
- cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
- cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
cp_start_hw(cp);
cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp)
cpw8(Config5, cpr8(Config5) & PMEStatus);
+ cpw32_f(HiTxRingAddr, 0);
+ cpw32_f(HiTxRingAddr + 4, 0);
+
+ ring_dma = cp->ring_dma;
+ cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+ ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+ cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+ cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
cpw16(MultiIntr, 0);
cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1060,17 +1060,22 @@ static int cp_init_rings (struct cp_private *cp)
static int cp_alloc_rings (struct cp_private *cp)
{
+ struct device *d = &cp->pdev->dev;
void *mem;
+ int rc;
- mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES,
- &cp->ring_dma, GFP_KERNEL);
+ mem = dma_alloc_coherent(d, CP_RING_BYTES, &cp->ring_dma, GFP_KERNEL);
if (!mem)
return -ENOMEM;
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
- return cp_init_rings(cp);
+ rc = cp_init_rings(cp);
+ if (rc < 0)
+ dma_free_coherent(d, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
+
+ return rc;
}
static void cp_clean_rings (struct cp_private *cp)
diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c
index fb9f6b38511f..edf5edb13140 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
netif_start_queue(net_dev);
/* Workaround for EDB */
- sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+ sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */
sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 77e6db9dcfed..a788501e978e 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -894,6 +894,8 @@ out:
return IRQ_HANDLED;
}
+static void axienet_dma_err_handler(unsigned long data);
+
/**
* axienet_open - Driver open routine.
* @ndev: Pointer to net_device structure
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 98934bdf6acf..477d6729b17f 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -1102,10 +1102,12 @@ static int init_queues(struct port *port)
{
int i;
- if (!ports_open)
- if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
- POOL_ALLOC_SIZE, 32, 0)))
+ if (!ports_open) {
+ dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+ POOL_ALLOC_SIZE, 32, 0);
+ if (!dma_pool)
return -ENOMEM;
+ }
if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
&port->desc_tab_phys)))
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index 5039f08f5a5b..43e9ab4f4d7e 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work)
break;
case SIRDEV_STATE_DONGLE_SPEED:
- if (dev->dongle_drv->reset) {
+ if (dev->dongle_drv->set_speed) {
ret = dev->dongle_drv->set_speed(dev, fsm->param);
if (ret < 0) {
fsm->result = ret;
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 899274f2f9b1..2ed1140df3e9 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
{
struct mdio_gpio_platform_data *pdata;
struct mii_bus *new_bus;
- int ret;
+ int ret, bus_id;
- if (pdev->dev.of_node)
+ if (pdev->dev.of_node) {
pdata = mdio_gpio_of_get_data(pdev);
- else
+ bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+ } else {
pdata = pdev->dev.platform_data;
+ bus_id = pdev->id;
+ }
if (!pdata)
return -ENODEV;
- new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+ new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id);
if (!new_bus)
return -ENODEV;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index d44cca327588..ad86660fb8f9 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1794,10 +1794,12 @@ static void team_setup(struct net_device *dev)
dev->features |= NETIF_F_LLTX;
dev->features |= NETIF_F_GRO;
- dev->hw_features = NETIF_F_HW_VLAN_TX |
+ dev->hw_features = TEAM_VLAN_FEATURES |
+ NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
+ dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
dev->features |= dev->hw_features;
}
diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c
index 9db0171e9366..c5db428e73fa 100644
--- a/drivers/net/team/team_mode_broadcast.c
+++ b/drivers/net/team/team_mode_broadcast.c
@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
if (last) {
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2) {
- ret = team_dev_queue_xmit(team, last,
- skb2);
+ ret = !team_dev_queue_xmit(team, last,
+ skb2);
if (!sum_ret)
sum_ret = ret;
}
@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
}
}
if (last) {
- ret = team_dev_queue_xmit(team, last, skb);
+ ret = !team_dev_queue_xmit(team, last, skb);
if (!sum_ret)
sum_ret = ret;
}
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3b566fa0f8e6..1ea91f4237f0 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -385,6 +385,7 @@ static const struct usb_device_id products[] = {
},
/* 3. Combined interface devices matching on interface number */
+ {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
{QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
{QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
{QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 3f575afd8cfc..760776b3d66c 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port)
{
int i;
- if (!ports_open)
- if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
- POOL_ALLOC_SIZE, 32, 0)))
+ if (!ports_open) {
+ dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+ POOL_ALLOC_SIZE, 32, 0);
+ if (!dma_pool)
return -ENOMEM;
+ }
if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
&port->desc_tab_phys)))
@@ -1363,7 +1365,7 @@ static int __devinit hss_init_one(struct platform_device *pdev)
platform_set_drvdata(pdev, port);
- netdev_info(dev, "HSS-%i\n", port->id);
+ netdev_info(dev, "initialized\n");
return 0;
err_free_netdev:
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 8e1559aba495..1829b445d0b0 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
switch (type) {
case ATH9K_RESET_POWER_ON:
ret = ath9k_hw_set_reset_power_on(ah);
- if (!ret)
+ if (ret)
ah->reset_power_on = true;
break;
case ATH9K_RESET_WARM:
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index fa4d1b8cd9f6..2d9eee93c743 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
vif_priv->ctx = ctx;
ctx->vif = vif;
+ /*
+ * In SNIFFER device type, the firmware reports the FCS to
+ * the host, rather than snipping it off. Unfortunately,
+ * mac80211 doesn't (yet) provide a per-packet flag for
+ * this, so that we have to set the hardware flag based
+ * on the interfaces added. As the monitor interface can
+ * only be present by itself, and will be removed before
+ * other interfaces are added, this is safe.
+ */
+ if (vif->type == NL80211_IFTYPE_MONITOR)
+ priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
+ else
+ priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
err = iwl_setup_interface(priv, ctx);
if (!err || reset)
goto out;
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 10896393e5a0..2830ea290502 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -1012,12 +1012,12 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
* As a consequence, it's not as complicated as it sounds, just add
* any lower rates to the ACK rate bitmap.
*/
- if (IWL_RATE_11M_INDEX < lowest_present_ofdm)
- ofdm |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
- if (IWL_RATE_5M_INDEX < lowest_present_ofdm)
- ofdm |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
- if (IWL_RATE_2M_INDEX < lowest_present_ofdm)
- ofdm |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
+ if (IWL_RATE_11M_INDEX < lowest_present_cck)
+ cck |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
+ if (IWL_RATE_5M_INDEX < lowest_present_cck)
+ cck |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
+ if (IWL_RATE_2M_INDEX < lowest_present_cck)
+ cck |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
/* 1M already there or needed so always add */
cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE;
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 105e3af3c621..79a4ddc002d3 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- u16 rd_ptr, wr_ptr;
- int n_bd = trans_pcie->txq[txq_id].q.n_bd;
if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
WARN_ONCE(1, "queue %d not used", txq_id);
return;
}
- rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1);
- wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id));
-
- WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
- txq_id, rd_ptr, wr_ptr);
-
iwl_txq_set_inactive(trans, txq_id);
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
}
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 8d465107f52b..ae9010ed58de 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
return;
}
cmd_node = adapter->curr_cmd;
- if (cmd_node->wait_q_enabled)
- adapter->cmd_wait_q.status = -ETIMEDOUT;
-
if (cmd_node) {
adapter->dbg.timeout_cmd_id =
adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
@@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
adapter->ps_mode, adapter->ps_state);
+
+ if (cmd_node->wait_q_enabled) {
+ adapter->cmd_wait_q.status = -ETIMEDOUT;
+ wake_up_interruptible(&adapter->cmd_wait_q.wait);
+ mwifiex_cancel_pending_ioctl(adapter);
+ /* reset cmd_sent flag to unblock new commands */
+ adapter->cmd_sent = false;
+ }
}
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
mwifiex_init_fw_complete(adapter);
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index fc8a9bfa1248..82cf0fa2d9f6 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev)
struct sdio_mmc_card *card;
struct mwifiex_adapter *adapter;
mmc_pm_flag_t pm_flag = 0;
- int hs_actived = 0;
int i;
int ret = 0;
@@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
adapter = card->adapter;
/* Enable the Host Sleep */
- hs_actived = mwifiex_enable_hs(adapter);
- if (hs_actived) {
- pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n");
- ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (!mwifiex_enable_hs(adapter)) {
+ dev_err(adapter->dev, "cmd: failed to suspend\n");
+ return -EFAULT;
}
+ dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
/* Indicate device suspended */
adapter->is_suspended = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 9970c2b1b199..b7e6607e6b6d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
/*=== Customer ID ===*/
/****** 8188CU ********/
{RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+ {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/
{RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index caa011008cd0..fc24eb9b3948 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
/* Grant backend access to each skb fragment page. */
for (i = 0; i < frags; i++) {
skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+ struct page *page = skb_frag_page(frag);
- tx->flags |= XEN_NETTXF_more_data;
+ len = skb_frag_size(frag);
+ offset = frag->page_offset;
- id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
- np->tx_skbs[id].skb = skb_get(skb);
- tx = RING_GET_REQUEST(&np->tx, prod++);
- tx->id = id;
- ref = gnttab_claim_grant_reference(&np->gref_tx_head);
- BUG_ON((signed short)ref < 0);
+ /* Data must not cross a page boundary. */
+ BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
- mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
- gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
- mfn, GNTMAP_readonly);
+ /* Skip unused frames from start of page */
+ page += offset >> PAGE_SHIFT;
+ offset &= ~PAGE_MASK;
- tx->gref = np->grant_tx_ref[id] = ref;
- tx->offset = frag->page_offset;
- tx->size = skb_frag_size(frag);
- tx->flags = 0;
+ while (len > 0) {
+ unsigned long bytes;
+
+ BUG_ON(offset >= PAGE_SIZE);
+
+ bytes = PAGE_SIZE - offset;
+ if (bytes > len)
+ bytes = len;
+
+ tx->flags |= XEN_NETTXF_more_data;
+
+ id = get_id_from_freelist(&np->tx_skb_freelist,
+ np->tx_skbs);
+ np->tx_skbs[id].skb = skb_get(skb);
+ tx = RING_GET_REQUEST(&np->tx, prod++);
+ tx->id = id;
+ ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+ BUG_ON((signed short)ref < 0);
+
+ mfn = pfn_to_mfn(page_to_pfn(page));
+ gnttab_grant_foreign_access_ref(ref,
+ np->xbdev->otherend_id,
+ mfn, GNTMAP_readonly);
+
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = offset;
+ tx->size = bytes;
+ tx->flags = 0;
+
+ offset += bytes;
+ len -= bytes;
+
+ /* Next frame */
+ if (offset == PAGE_SIZE && len) {
+ BUG_ON(!PageCompound(page));
+ page++;
+ offset = 0;
+ }
+ }
}
np->tx.req_prod_pvt = prod;
}
+/*
+ * Count how many ring slots are required to send the frags of this
+ * skb. Each frag might be a compound page.
+ */
+static int xennet_count_skb_frag_slots(struct sk_buff *skb)
+{
+ int i, frags = skb_shinfo(skb)->nr_frags;
+ int pages = 0;
+
+ for (i = 0; i < frags; i++) {
+ skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+ unsigned long size = skb_frag_size(frag);
+ unsigned long offset = frag->page_offset;
+
+ /* Skip unused frames from start of page */
+ offset &= ~PAGE_MASK;
+
+ pages += PFN_UP(offset + size);
+ }
+
+ return pages;
+}
+
static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned short id;
@@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
grant_ref_t ref;
unsigned long mfn;
int notify;
- int frags = skb_shinfo(skb)->nr_frags;
+ int slots;
unsigned int offset = offset_in_page(data);
unsigned int len = skb_headlen(skb);
unsigned long flags;
- frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
- if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
- printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
- frags);
- dump_stack();
+ slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+ xennet_count_skb_frag_slots(skb);
+ if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+ net_alert_ratelimited(
+ "xennet: skb rides the rocket: %d slots\n", slots);
goto drop;
}
spin_lock_irqsave(&np->tx_lock, flags);
if (unlikely(!netif_carrier_ok(dev) ||
- (frags > 1 && !xennet_can_sg(dev)) ||
+ (slots > 1 && !xennet_can_sg(dev)) ||
netif_needs_gso(skb, netif_skb_features(skb)))) {
spin_unlock_irqrestore(&np->tx_lock, flags);
goto drop;
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 97c440a8cd61..30ae18a03a9c 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work)
cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
+ list_del(&cmd->queue);
+
mutex_unlock(&dev->cmd_lock);
__pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame,
cmd->in_frame_len, cmd->cmd_complete,
cmd->arg, cmd->flags);
- list_del(&cmd->queue);
kfree(cmd);
}
@@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
u8 *params, int params_len)
{
- struct pn533_cmd_jump_dep *cmd;
struct pn533_cmd_jump_dep_response *resp;
struct nfc_target nfc_target;
u8 target_gt_len;
int rc;
+ struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg;
+ u8 active = cmd->active;
+
+ kfree(arg);
if (params_len == -ENOENT) {
nfc_dev_dbg(&dev->interface->dev, "");
@@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
}
resp = (struct pn533_cmd_jump_dep_response *) params;
- cmd = (struct pn533_cmd_jump_dep *) arg;
rc = resp->status & PN533_CMD_RET_MASK;
if (rc != PN533_CMD_RET_SUCCESS) {
nfc_dev_err(&dev->interface->dev,
@@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
if (rc == 0)
rc = nfc_dep_link_is_up(dev->nfc_dev,
dev->nfc_dev->targets[0].idx,
- !cmd->active, NFC_RF_INITIATOR);
+ !active, NFC_RF_INITIATOR);
return 0;
}
@@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
dev->in_maxlen, pn533_in_dep_link_up_complete,
cmd, GFP_KERNEL);
- if (rc)
- goto out;
-
-
-out:
- kfree(cmd);
+ if (rc < 0)
+ kfree(cmd);
return rc;
}
@@ -2078,8 +2077,12 @@ error:
static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
u8 *params, int params_len)
{
+ struct sk_buff *skb_out = arg;
+
nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+ dev_kfree_skb(skb_out);
+
if (params_len < 0) {
nfc_dev_err(&dev->interface->dev,
"Error %d when sending data",
@@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
dev->in_maxlen, pn533_tm_send_complete,
- NULL, GFP_KERNEL);
+ skb, GFP_KERNEL);
if (rc) {
nfc_dev_err(&dev->interface->dev,
"Error %d when trying to send data", rc);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index af3b22ac7627..538e3cfad23e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -45,7 +45,8 @@ struct alias_prop {
static LIST_HEAD(aliases_lookup);
-struct device_node *allnodes;
+struct device_node *of_allnodes;
+EXPORT_SYMBOL(of_allnodes);
struct device_node *of_chosen;
struct device_node *of_aliases;
@@ -199,7 +200,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
struct device_node *np;
read_lock(&devtree_lock);
- np = prev ? prev->allnext : allnodes;
+ np = prev ? prev->allnext : of_allnodes;
for (; np != NULL; np = np->allnext)
if (of_node_get(np))
break;
@@ -422,7 +423,7 @@ EXPORT_SYMBOL(of_get_child_by_name);
*/
struct device_node *of_find_node_by_path(const char *path)
{
- struct device_node *np = allnodes;
+ struct device_node *np = of_allnodes;
read_lock(&devtree_lock);
for (; np; np = np->allnext) {
@@ -452,7 +453,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->name && (of_node_cmp(np->name, name) == 0)
&& of_node_get(np))
@@ -481,7 +482,7 @@ struct device_node *of_find_node_by_type(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->type && (of_node_cmp(np->type, type) == 0)
&& of_node_get(np))
@@ -512,7 +513,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
if (type
&& !(np->type && (of_node_cmp(np->type, type) == 0)))
@@ -545,7 +546,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
struct property *pp;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
for (pp = np->properties; pp; pp = pp->next) {
if (of_prop_cmp(pp->name, prop_name) == 0) {
@@ -594,27 +595,35 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
EXPORT_SYMBOL(of_match_node);
/**
- * of_find_matching_node - Find a node based on an of_device_id match
- * table.
+ * of_find_matching_node_and_match - Find a node based on an of_device_id
+ * match table.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @matches: array of of device match structures to search in
+ * @match Updated to point at the matches entry which matched
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
-struct device_node *of_find_matching_node(struct device_node *from,
- const struct of_device_id *matches)
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+ const struct of_device_id *matches,
+ const struct of_device_id **match)
{
struct device_node *np;
+ if (match)
+ *match = NULL;
+
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
- if (of_match_node(matches, np) && of_node_get(np))
+ if (of_match_node(matches, np) && of_node_get(np)) {
+ if (match)
+ *match = matches;
break;
+ }
}
of_node_put(from);
read_unlock(&devtree_lock);
@@ -661,7 +670,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
struct device_node *np;
read_lock(&devtree_lock);
- for (np = allnodes; np; np = np->allnext)
+ for (np = of_allnodes; np; np = np->allnext)
if (np->phandle == handle)
break;
of_node_get(np);
@@ -671,12 +680,89 @@ struct device_node *of_find_node_by_phandle(phandle handle)
EXPORT_SYMBOL(of_find_node_by_phandle);
/**
+ * of_property_read_u8_array - Find and read an array of u8 from a property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
+ *
+ * Search for a property in a device node and read 8-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ * property = /bits/ 8 <0x50 0x60 0x70>;
+ *
+ * The out_value is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values, size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const u8 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = *val++;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_array);
+
+/**
+ * of_property_read_u16_array - Find and read an array of u16 from a property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
+ *
+ * Search for a property in a device node and read 16-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ * property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *
+ * The out_value is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values, size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const __be16 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = be16_to_cpup(val++);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u16_array);
+
+/**
* of_property_read_u32_array - Find and read an array of 32 bit integers
* from a property.
*
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
* @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
*
* Search for a property in a device node and read 32-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
@@ -893,8 +979,8 @@ EXPORT_SYMBOL_GPL(of_property_count_strings);
* Returns the device_node pointer with refcount incremented. Use
* of_node_put() on it when done.
*/
-struct device_node *
-of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
+struct device_node *of_parse_phandle(const struct device_node *np,
+ const char *phandle_name, int index)
{
const __be32 *phandle;
int size;
@@ -1169,9 +1255,9 @@ void of_attach_node(struct device_node *np)
write_lock_irqsave(&devtree_lock, flags);
np->sibling = np->parent->child;
- np->allnext = allnodes;
+ np->allnext = of_allnodes;
np->parent->child = np;
- allnodes = np;
+ of_allnodes = np;
write_unlock_irqrestore(&devtree_lock, flags);
}
@@ -1192,11 +1278,11 @@ void of_detach_node(struct device_node *np)
if (!parent)
goto out_unlock;
- if (allnodes == np)
- allnodes = np->allnext;
+ if (of_allnodes == np)
+ of_allnodes = np->allnext;
else {
struct device_node *prev;
- for (prev = allnodes;
+ for (prev = of_allnodes;
prev->allnext != np;
prev = prev->allnext)
;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 91a375fb6ae6..a65c39c473bf 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -186,6 +186,8 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
*/
fpsize = 1;
allocl = 2;
+ l = 1;
+ *pathp = '\0';
} else {
/* account for '/' and path size minus terminal 0
* already in 'l'
@@ -198,10 +200,10 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
__alignof__(struct device_node));
if (allnextpp) {
+ char *fn;
memset(np, 0, sizeof(*np));
- np->full_name = ((char *)np) + sizeof(struct device_node);
+ np->full_name = fn = ((char *)np) + sizeof(*np);
if (new_format) {
- char *fn = np->full_name;
/* rebuild full path for new format */
if (dad && dad->parent) {
strcpy(fn, dad->full_name);
@@ -215,9 +217,9 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
fn += strlen(fn);
}
*(fn++) = '/';
- memcpy(fn, pathp, l);
- } else
- memcpy(np->full_name, pathp, l);
+ }
+ memcpy(fn, pathp, l);
+
prev_pp = &np->properties;
**allnextpp = np;
*allnextpp = &np->allnext;
@@ -459,7 +461,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
do {
u32 tag = be32_to_cpup((__be32 *)p);
- char *pathp;
+ const char *pathp;
p += 4;
if (tag == OF_DT_END_NODE) {
@@ -487,7 +489,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
pathp = (char *)p;
p = ALIGN(p + strlen(pathp) + 1, 4);
if ((*pathp) == '/') {
- char *lp, *np;
+ const char *lp, *np;
for (lp = NULL, np = pathp; *np; np++)
if ((*np) == '/')
lp = np+1;
@@ -710,7 +712,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
*/
void __init unflatten_device_tree(void)
{
- __unflatten_device_tree(initial_boot_params, &allnodes,
+ __unflatten_device_tree(initial_boot_params, &of_allnodes,
early_init_dt_alloc_memory_arch);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 3550f3bf4f92..b667264222cc 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -29,7 +29,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
- for_each_child_of_node(adap->dev.of_node, node) {
+ for_each_available_child_of_node(adap->dev.of_node, node) {
struct i2c_board_info info = {};
struct dev_archdata dev_ad = {};
const __be32 *addr;
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 8e6c25f35040..83ca06f4312b 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -53,7 +53,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
return rc;
/* Loop over the child nodes and register a phy_device for each one */
- for_each_child_of_node(np, child) {
+ for_each_available_child_of_node(np, child) {
const __be32 *paddr;
u32 addr;
int len;
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 07cc1d678e4d..37b56fd716e6 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -241,15 +241,15 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
BUG_ON(!ops);
of_pdt_prom_ops = ops;
- allnodes = of_pdt_create_node(root_node, NULL);
+ of_allnodes = of_pdt_create_node(root_node, NULL);
#if defined(CONFIG_SPARC)
- allnodes->path_component_name = "";
+ of_allnodes->path_component_name = "";
#endif
- allnodes->full_name = "/";
+ of_allnodes->full_name = "/";
- nextp = &allnodes->allnext;
- allnodes->child = of_pdt_build_tree(allnodes,
- of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+ nextp = &of_allnodes->allnext;
+ of_allnodes->child = of_pdt_build_tree(of_allnodes,
+ of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(kernel_tree_alloc);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 4b6e4e7aca8f..0e60438ebe30 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -57,8 +57,8 @@ config PARPORT_SERIAL
will be called parport_serial.
config PARPORT_PC_FIFO
- bool "Use FIFO/DMA if available (EXPERIMENTAL)"
- depends on PARPORT_PC && EXPERIMENTAL
+ bool "Use FIFO/DMA if available"
+ depends on PARPORT_PC
help
Many parallel port chipsets provide hardware that can speed up
printing. Say Y here if you want to take advantage of that.
@@ -70,8 +70,8 @@ config PARPORT_PC_FIFO
specify which IRQ/DMA to use.
config PARPORT_PC_SUPERIO
- bool "SuperIO chipset support (EXPERIMENTAL)"
- depends on PARPORT_PC && EXPERIMENTAL
+ bool "SuperIO chipset support"
+ depends on PARPORT_PC
help
Saying Y here enables some probes for Super-IO chipsets in order to
find out things like base addresses, IRQ lines and DMA channels. It
@@ -85,8 +85,8 @@ config PARPORT_PC_PCMCIA
ports. If unsure, say N.
config PARPORT_IP32
- tristate "SGI IP32 builtin port (EXPERIMENTAL)"
- depends on SGI_IP32 && EXPERIMENTAL
+ tristate "SGI IP32 builtin port"
+ depends on SGI_IP32
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port on
@@ -126,8 +126,8 @@ config PARPORT_GSC
select PARPORT_NOT_PC
config PARPORT_SUNBPP
- tristate "Sparc hardware (EXPERIMENTAL)"
- depends on SBUS && EXPERIMENTAL
+ tristate "Sparc hardware"
+ depends on SBUS
select PARPORT_NOT_PC
help
This driver provides support for the bidirectional parallel port
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 8d688b260e28..0c3efcffa83b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,7 @@
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
+ irq.o vpd.o setup-bus.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o
@@ -15,8 +15,6 @@ obj-$(CONFIG_PCIEPORTBUS) += pcie/
obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
-obj-$(CONFIG_HOTPLUG) += hotplug.o
-
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
ifdef CONFIG_HOTPLUG_PCI
@@ -60,9 +58,6 @@ obj-$(CONFIG_ACPI) += pci-acpi.o
# SMBIOS provided firmware instance and labels
obj-$(CONFIG_PCI_LABEL) += pci-label.o
-# Cardbus & CompactPCI use setup-bus
-obj-$(CONFIG_HOTPLUG) += setup-bus.o
-
obj-$(CONFIG_PCI_SYSCALL) += syscall.o
obj-$(CONFIG_PCI_STUB) += pci-stub.o
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
deleted file mode 100644
index 2b5352a7dffc..000000000000
--- a/drivers/pci/hotplug.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/module.h>
-#include "pci.h"
-
-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct pci_dev *pdev;
-
- if (!dev)
- return -ENODEV;
-
- pdev = to_pci_dev(dev);
- if (!pdev)
- return -ENODEV;
-
- if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
- return -ENOMEM;
-
- if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
- return -ENOMEM;
-
- if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device))
- return -ENOMEM;
-
- if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
- return -ENOMEM;
-
- if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
- pdev->vendor, pdev->device,
- pdev->subsystem_vendor, pdev->subsystem_device,
- (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
- (u8)(pdev->class)))
- return -ENOMEM;
- return 0;
-}
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index 6bf8d2ab164f..449b4bbc8301 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -271,7 +271,7 @@ init_hc_error:
}
-static void __devexit zt5550_hc_remove_one(struct pci_dev *pdev)
+static void zt5550_hc_remove_one(struct pci_dev *pdev)
{
cpci_hp_stop();
cpci_hp_unregister_bus(bus0);
@@ -290,7 +290,7 @@ static struct pci_driver zt5550_hc_driver = {
.name = "zt5550_hc",
.id_table = zt5550_hc_pci_tbl,
.probe = zt5550_hc_init_one,
- .remove = __devexit_p(zt5550_hc_remove_one),
+ .remove = zt5550_hc_remove_one,
};
static int __init zt5550_init(void)
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 205af8dc83c2..2eca902a4283 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -27,7 +27,7 @@ struct ioapic {
u32 gsi_base;
};
-static int __devinit ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
acpi_handle handle;
acpi_status status;
@@ -88,7 +88,7 @@ exit_free:
return -ENODEV;
}
-static void __devexit ioapic_remove(struct pci_dev *dev)
+static void ioapic_remove(struct pci_dev *dev)
{
struct ioapic *ioapic = pci_get_drvdata(dev);
@@ -110,7 +110,7 @@ static struct pci_driver ioapic_driver = {
.name = "ioapic",
.id_table = ioapic_devices,
.probe = ioapic_probe,
- .remove = __devexit_p(ioapic_remove),
+ .remove = ioapic_remove,
};
static int __init ioapic_init(void)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c5792d622dc4..1af4008182fd 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -17,10 +17,9 @@
#include <linux/pci-acpi.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
#include "pci.h"
-static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
-
/**
* pci_acpi_wake_bus - Wake-up notification handler for root buses.
* @handle: ACPI handle of a device the notification is for.
@@ -68,67 +67,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
}
/**
- * add_pm_notifier - Register PM notifier for given ACPI device.
- * @dev: ACPI device to add the notifier for.
- * @context: PCI device or bus to check for PME status if an event is signaled.
- *
- * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
- * PM wake-up events. For example, wake-up events may be generated for bridges
- * if one of the devices below the bridge is signaling PME, even if the bridge
- * itself doesn't have a wake-up GPE associated with it.
- */
-static acpi_status add_pm_notifier(struct acpi_device *dev,
- acpi_notify_handler handler,
- void *context)
-{
- acpi_status status = AE_ALREADY_EXISTS;
-
- mutex_lock(&pci_acpi_pm_notify_mtx);
-
- if (dev->wakeup.flags.notifier_present)
- goto out;
-
- status = acpi_install_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
- handler, context);
- if (ACPI_FAILURE(status))
- goto out;
-
- dev->wakeup.flags.notifier_present = true;
-
- out:
- mutex_unlock(&pci_acpi_pm_notify_mtx);
- return status;
-}
-
-/**
- * remove_pm_notifier - Unregister PM notifier from given ACPI device.
- * @dev: ACPI device to remove the notifier from.
- */
-static acpi_status remove_pm_notifier(struct acpi_device *dev,
- acpi_notify_handler handler)
-{
- acpi_status status = AE_BAD_PARAMETER;
-
- mutex_lock(&pci_acpi_pm_notify_mtx);
-
- if (!dev->wakeup.flags.notifier_present)
- goto out;
-
- status = acpi_remove_notify_handler(dev->handle,
- ACPI_SYSTEM_NOTIFY,
- handler);
- if (ACPI_FAILURE(status))
- goto out;
-
- dev->wakeup.flags.notifier_present = false;
-
- out:
- mutex_unlock(&pci_acpi_pm_notify_mtx);
- return status;
-}
-
-/**
* pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
* @dev: ACPI device to add the notifier for.
* @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
@@ -136,7 +74,7 @@ static acpi_status remove_pm_notifier(struct acpi_device *dev,
acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
struct pci_bus *pci_bus)
{
- return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
+ return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
}
/**
@@ -145,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
*/
acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
{
- return remove_pm_notifier(dev, pci_acpi_wake_bus);
+ return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
}
/**
@@ -156,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
struct pci_dev *pci_dev)
{
- return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
+ return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
}
/**
@@ -165,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
*/
acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
{
- return remove_pm_notifier(dev, pci_acpi_wake_dev);
+ return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
}
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -257,11 +195,16 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
return -ENODEV;
switch (state) {
+ case PCI_D3cold:
+ if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
+ PM_QOS_FLAGS_ALL) {
+ error = -EBUSY;
+ break;
+ }
case PCI_D0:
case PCI_D1:
case PCI_D2:
case PCI_D3hot:
- case PCI_D3cold:
error = acpi_bus_set_power(handle, state_conv[state]);
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6c94fc9489e7..1dc78c5cabf8 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -89,10 +89,6 @@ static void pci_free_dynids(struct pci_driver *drv)
spin_unlock(&drv->dynids.lock);
}
-/*
- * Dynamic device ID manipulation via sysfs is disabled for !CONFIG_HOTPLUG
- */
-#ifdef CONFIG_HOTPLUG
/**
* store_new_id - sysfs frontend to pci_add_dynid()
* @driver: target device driver
@@ -191,10 +187,6 @@ static struct driver_attribute pci_drv_attrs[] = {
__ATTR_NULL,
};
-#else
-#define pci_drv_attrs NULL
-#endif /* CONFIG_HOTPLUG */
-
/**
* pci_match_id - See if a pci device matches a given pci_id table
* @ids: array of PCI device id structures to search in
@@ -1223,12 +1215,38 @@ void pci_dev_put(struct pci_dev *dev)
put_device(&dev->dev);
}
-#ifndef CONFIG_HOTPLUG
-int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
+static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
{
- return -ENODEV;
+ struct pci_dev *pdev;
+
+ if (!dev)
+ return -ENODEV;
+
+ pdev = to_pci_dev(dev);
+ if (!pdev)
+ return -ENODEV;
+
+ if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+ pdev->subsystem_device))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class)))
+ return -ENOMEM;
+ return 0;
}
-#endif
struct bus_type pci_bus_type = {
.name = "pci",
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index f39378d9da15..68d56f02e721 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -284,7 +284,6 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
return count;
}
-#ifdef CONFIG_HOTPLUG
static DEFINE_MUTEX(pci_remove_rescan_mutex);
static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
size_t count)
@@ -377,8 +376,6 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
return count;
}
-#endif
-
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
static ssize_t d3cold_allowed_store(struct device *dev,
struct device_attribute *attr,
@@ -424,10 +421,8 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
broken_parity_status_show,broken_parity_status_store),
__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
-#ifdef CONFIG_HOTPLUG
__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
-#endif
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
#endif
@@ -435,9 +430,7 @@ struct device_attribute pci_dev_attrs[] = {
};
struct device_attribute pcibus_dev_attrs[] = {
-#ifdef CONFIG_HOTPLUG
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
-#endif
__ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
__ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
__ATTR_NULL,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index aabf64798bda..bdf66b500f22 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -86,7 +86,7 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
* the dfl or actual value as it sees fit. Don't forget this is
* measured in 32-bit words, not bytes.
*/
-u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
+u8 pci_dfl_cache_line_size = L1_CACHE_BYTES >> 2;
u8 pci_cache_line_size;
/*
@@ -3857,7 +3857,7 @@ static int __init pci_resource_alignment_sysfs_init(void)
late_initcall(pci_resource_alignment_sysfs_init);
-static void __devinit pci_no_domains(void)
+static void pci_no_domains(void)
{
#ifdef CONFIG_PCI_DOMAINS
pci_domains_supported = 0;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fd92aab9904b..e253881c4275 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -8,7 +8,6 @@
/* Functions internal to the PCI core code */
-extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
@@ -159,11 +158,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
}
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[];
-#ifdef CONFIG_HOTPLUG
extern struct bus_attribute pci_bus_attrs[];
-#else
-#define pci_bus_attrs NULL
-#endif
/**
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 030cf12d5468..76ef634caf6f 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -41,7 +41,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static int __devinit aer_probe(struct pcie_device *dev);
+static int aer_probe(struct pcie_device *dev);
static void aer_remove(struct pcie_device *dev);
static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
enum pci_channel_state error);
@@ -300,7 +300,7 @@ static void aer_remove(struct pcie_device *dev)
*
* Invoked when PCI Express bus loads AER service driver.
*/
-static int __devinit aer_probe(struct pcie_device *dev)
+static int aer_probe(struct pcie_device *dev)
{
int status;
struct aer_rpc *rpc;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 0761d90ca279..d4824cb78b49 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -182,7 +182,7 @@ static const struct pci_device_id port_runtime_pm_black_list[] = {
* this port device.
*
*/
-static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
+static int pcie_portdrv_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int status;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ec909afa90b6..3683f6094e3f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -305,7 +305,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
}
}
-static void __devinit pci_read_bridge_io(struct pci_bus *child)
+static void pci_read_bridge_io(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
u8 io_base_lo, io_limit_lo;
@@ -345,7 +345,7 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
}
}
-static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
+static void pci_read_bridge_mmio(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
u16 mem_base_lo, mem_limit_lo;
@@ -367,7 +367,7 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
}
}
-static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
+static void pci_read_bridge_mmio_pref(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
u16 mem_base_lo, mem_limit_lo;
@@ -417,7 +417,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
}
}
-void __devinit pci_read_bridge_bases(struct pci_bus *child)
+void pci_read_bridge_bases(struct pci_bus *child)
{
struct pci_dev *dev = child->self;
struct resource *res;
@@ -705,7 +705,7 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
* them, we proceed to assigning numbers to the remaining buses in
* order to avoid overlaps between old and new bus numbers.
*/
-int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
@@ -1586,7 +1586,7 @@ void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
}
EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
-unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
+unsigned int pci_scan_child_bus(struct pci_bus *bus)
{
unsigned int devfn, pass, max = bus->busn_res.start;
struct pci_dev *dev;
@@ -1790,7 +1790,7 @@ void pci_bus_release_busn_res(struct pci_bus *b)
res, ret ? "can not be" : "is");
}
-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
struct pci_host_bridge_window *window;
@@ -1826,7 +1826,7 @@ struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
EXPORT_SYMBOL(pci_scan_root_bus);
/* Deprecated; use pci_scan_root_bus() instead */
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+struct pci_bus *pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
LIST_HEAD(resources);
@@ -1844,7 +1844,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
}
EXPORT_SYMBOL(pci_scan_bus_parented);
-struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
+struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
void *sysdata)
{
LIST_HEAD(resources);
@@ -1864,7 +1864,6 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
}
EXPORT_SYMBOL(pci_scan_bus);
-#ifdef CONFIG_HOTPLUG
/**
* pci_rescan_bus_bridge_resize - scan a PCI bus for devices.
* @bridge: PCI bridge for the bus to scan
@@ -1894,7 +1893,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge);
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
-#endif
static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
{
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7a451ff56ecc..22ad3ee0cf0b 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -37,7 +37,7 @@
* key system devices. For devices that need to have mmio decoding always-on,
* we need to set the dev->mmio_always_on bit.
*/
-static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
+static void quirk_mmio_always_on(struct pci_dev *dev)
{
dev->mmio_always_on = 1;
}
@@ -48,7 +48,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
* Mark this device with a broken_parity_status, to allow
* PCI scanning code to "skip" this now blacklisted device.
*/
-static void __devinit quirk_mellanox_tavor(struct pci_dev *dev)
+static void quirk_mellanox_tavor(struct pci_dev *dev)
{
dev->broken_parity_status = 1; /* This device gives false positives */
}
@@ -83,7 +83,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_p
This appears to be BIOS not version dependent. So presumably there is a
chipset level fix */
-static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
+static void quirk_isa_dma_hangs(struct pci_dev *dev)
{
if (!isa_dma_bridge_buggy) {
isa_dma_bridge_buggy=1;
@@ -106,7 +106,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_d
* Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
* for some HT machines to use C4 w/o hanging.
*/
-static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+static void quirk_tigerpoint_bm_sts(struct pci_dev *dev)
{
u32 pmbase;
u16 pm1a;
@@ -125,7 +125,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk
/*
* Chipsets where PCI->PCI transfers vanish or hang
*/
-static void __devinit quirk_nopcipci(struct pci_dev *dev)
+static void quirk_nopcipci(struct pci_dev *dev)
{
if ((pci_pci_problems & PCIPCI_FAIL)==0) {
dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
@@ -135,7 +135,7 @@ static void __devinit quirk_nopcipci(struct pci_dev *dev)
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci);
-static void __devinit quirk_nopciamd(struct pci_dev *dev)
+static void quirk_nopciamd(struct pci_dev *dev)
{
u8 rev;
pci_read_config_byte(dev, 0x08, &rev);
@@ -150,7 +150,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopci
/*
* Triton requires workarounds to be used by the drivers
*/
-static void __devinit quirk_triton(struct pci_dev *dev)
+static void quirk_triton(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_TRITON)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -229,7 +229,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_viala
/*
* VIA Apollo VP3 needs ETBF on BT848/878
*/
-static void __devinit quirk_viaetbf(struct pci_dev *dev)
+static void quirk_viaetbf(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -238,7 +238,7 @@ static void __devinit quirk_viaetbf(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf);
-static void __devinit quirk_vsfx(struct pci_dev *dev)
+static void quirk_vsfx(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VSFX)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx)
* workaround applied too
* [Info kindly provided by ALi]
*/
-static void __devinit quirk_alimagik(struct pci_dev *dev)
+static void quirk_alimagik(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -267,7 +267,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimag
* Natoma has some interesting boundary conditions with Zoran stuff
* at least
*/
-static void __devinit quirk_natoma(struct pci_dev *dev)
+static void quirk_natoma(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
@@ -285,7 +285,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, qu
* This chip can cause PCI parity errors if config register 0xA0 is read
* while DMAs are occurring.
*/
-static void __devinit quirk_citrine(struct pci_dev *dev)
+static void quirk_citrine(struct pci_dev *dev)
{
dev->cfg_size = 0xA0;
}
@@ -295,7 +295,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_cit
* S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
* If it's needed, re-allocate the region.
*/
-static void __devinit quirk_s3_64M(struct pci_dev *dev)
+static void quirk_s3_64M(struct pci_dev *dev)
{
struct resource *r = &dev->resource[0];
@@ -313,7 +313,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
* BAR0 should be 8 bytes; instead, it may be set to something like 8k
* (which conflicts w/ BAR1's memory range).
*/
-static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
+static void quirk_cs5536_vsa(struct pci_dev *dev)
{
if (pci_resource_len(dev, 0) != 8) {
struct resource *res = &dev->resource[0];
@@ -324,7 +324,7 @@ static void __devinit quirk_cs5536_vsa(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
-static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
+static void quirk_io_region(struct pci_dev *dev, unsigned region,
unsigned size, int nr, const char *name)
{
region &= ~(size-1);
@@ -352,7 +352,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
* ATI Northbridge setups MCE the processor if you even
* read somewhere between 0x3b0->0x3bb or read 0x3d3
*/
-static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
+static void quirk_ati_exploding_mce(struct pci_dev *dev)
{
dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
@@ -372,7 +372,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_
* 0xE0 (64 bytes of ACPI registers)
* 0xE2 (32 bytes of SMB registers)
*/
-static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
+static void quirk_ali7101_acpi(struct pci_dev *dev)
{
u16 region;
@@ -440,7 +440,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
* 0x90 (16 bytes of SMB registers)
* and a few strange programmable PIIX4 device resources.
*/
-static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
+static void quirk_piix4_acpi(struct pci_dev *dev)
{
u32 region, res_a;
@@ -489,7 +489,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui
* 0x40 (128 bytes of ACPI, GPIO & TCO registers)
* 0x58 (64 bytes of GPIO I/O space)
*/
-static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
+static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
{
u32 region;
u8 enable;
@@ -531,7 +531,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi);
-static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
+static void ich6_lpc_acpi_gpio(struct pci_dev *dev)
{
u32 region;
u8 enable;
@@ -555,7 +555,7 @@ static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
}
}
-static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
+static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
{
u32 val;
u32 size, base;
@@ -583,7 +583,7 @@ static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base+size-1);
}
-static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
+static void quirk_ich6_lpc(struct pci_dev *dev)
{
/* Shared ACPI/GPIO decode with all ICH6+ */
ich6_lpc_acpi_gpio(dev);
@@ -595,7 +595,7 @@ static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc);
-static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
+static void ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
{
u32 val;
u32 mask, base;
@@ -619,7 +619,7 @@ static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg,
}
/* ICH7-10 has the same common LPC generic IO decode registers */
-static void __devinit quirk_ich7_lpc(struct pci_dev *dev)
+static void quirk_ich7_lpc(struct pci_dev *dev)
{
/* We share the common ACPI/GPIO decode with ICH6 */
ich6_lpc_acpi_gpio(dev);
@@ -648,7 +648,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_1, qui
* VIA ACPI: One IO region pointed to by longword at
* 0x48 or 0x20 (256 bytes of ACPI registers)
*/
-static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
+static void quirk_vt82c586_acpi(struct pci_dev *dev)
{
u32 region;
@@ -666,7 +666,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt
* 0x70 (128 bytes of hardware monitoring register)
* 0x90 (16 bytes of SMB registers)
*/
-static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
+static void quirk_vt82c686_acpi(struct pci_dev *dev)
{
u16 hm;
u32 smb;
@@ -688,7 +688,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt
* 0x88 (128 bytes of power management registers)
* 0xd0 (16 bytes of SMB registers)
*/
-static void __devinit quirk_vt8235_acpi(struct pci_dev *dev)
+static void quirk_vt8235_acpi(struct pci_dev *dev)
{
u16 pm, smb;
@@ -706,7 +706,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235
* TI XIO2000a PCIe-PCI Bridge erroneously reports it supports fast back-to-back:
* Disable fast back-to-back on the secondary bus segment
*/
-static void __devinit quirk_xio2000a(struct pci_dev *dev)
+static void quirk_xio2000a(struct pci_dev *dev)
{
struct pci_dev *pdev;
u16 command;
@@ -780,7 +780,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk
* noapic specified. For the moment we assume it's the erratum. We may be wrong
* of course. However the advice is demonstrably good even if so..
*/
-static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
+static void quirk_amd_ioapic(struct pci_dev *dev)
{
if (dev->revision >= 0x02) {
dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
@@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic);
-static void __devinit quirk_ioapic_rmw(struct pci_dev *dev)
+static void quirk_ioapic_rmw(struct pci_dev *dev)
{
if (dev->devfn == 0 && dev->bus->number == 0)
sis_apic_bug = 1;
@@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw);
* Some settings of MMRBC can lead to data corruption so block changes.
* See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
*/
-static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev)
+static void quirk_amd_8131_mmrbc(struct pci_dev *dev)
{
if (dev->subordinate && dev->revision <= 0x12) {
dev_info(&dev->dev, "AMD8131 rev %x detected; "
@@ -819,7 +819,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
* value of the ACPI SCI interrupt is only done for convenience.
* -jgarzik
*/
-static void __devinit quirk_via_acpi(struct pci_dev *d)
+static void quirk_via_acpi(struct pci_dev *d)
{
/*
* VIA ACPI device: SCI IRQ line in PCI config byte 0x42
@@ -926,7 +926,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_vlink);
* We need to switch it off to be able to recognize the real
* type of the chip.
*/
-static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
+static void quirk_vt82c598_id(struct pci_dev *dev)
{
pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
@@ -978,7 +978,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C
* assigned to it. We force a larger allocation to ensure that
* nothing gets put too close to it.
*/
-static void __devinit quirk_dunord ( struct pci_dev * dev )
+static void quirk_dunord(struct pci_dev *dev)
{
struct resource *r = &dev->resource [1];
r->start = 0;
@@ -992,7 +992,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk
* in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
* instead of 0x01.
*/
-static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
+static void quirk_transparent_bridge(struct pci_dev *dev)
{
dev->transparent = 1;
}
@@ -1066,7 +1066,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA
/*
* Serverworks CSB5 IDE does not fully support native mode
*/
-static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
+static void quirk_svwks_csb5ide(struct pci_dev *pdev)
{
u8 prog;
pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
@@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
*/
-static void __devinit quirk_ide_samemode(struct pci_dev *pdev)
+static void quirk_ide_samemode(struct pci_dev *pdev)
{
u8 prog;
@@ -1101,7 +1101,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, qui
* Some ATA devices break if put into D3
*/
-static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
+static void quirk_no_ata_d3(struct pci_dev *pdev)
{
pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
}
@@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
*/
-static void __devinit quirk_eisa_bridge(struct pci_dev *dev)
+static void quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
@@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
*/
static int asus_hides_smbus;
-static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev)
+static void asus_hides_smbus_hostbridge(struct pci_dev *dev)
{
if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
@@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
#endif
#ifdef CONFIG_X86_IO_APIC
-static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
+static void quirk_alder_ioapic(struct pci_dev *pdev)
{
int i;
@@ -1561,7 +1561,7 @@ static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
#endif
-static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
+static void quirk_pcie_mch(struct pci_dev *pdev)
{
pci_msi_off(pdev);
pdev->no_msi = 1;
@@ -1575,7 +1575,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quir
* It's possible for the MSI to get corrupted if shpc and acpi
* are used together on certain PXH-based systems.
*/
-static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
+static void quirk_pcie_pxh(struct pci_dev *dev)
{
pci_msi_off(dev);
dev->no_msi = 1;
@@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, qui
* but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
* Re-allocate the region if needed...
*/
-static void __devinit quirk_tc86c001_ide(struct pci_dev *dev)
+static void quirk_tc86c001_ide(struct pci_dev *dev)
{
struct resource *r = &dev->resource[0];
@@ -1790,7 +1790,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
quirk_tc86c001_ide);
-static void __devinit quirk_netmos(struct pci_dev *dev)
+static void quirk_netmos(struct pci_dev *dev)
{
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
unsigned int num_serial = dev->subsystem_device & 0xf;
@@ -1828,7 +1828,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
-static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
+static void quirk_e100_interrupt(struct pci_dev *dev)
{
u16 command, pmcsr;
u8 __iomem *csr;
@@ -1901,7 +1901,7 @@ DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
* The 82575 and 82598 may experience data corruption issues when transitioning
* out of L0S. To prevent this we need to disable L0S on the pci-e link
*/
-static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev)
+static void quirk_disable_aspm_l0s(struct pci_dev *dev)
{
dev_info(&dev->dev, "Disabling L0s\n");
pci_disable_link_state(dev, PCIE_LINK_STATE_L0S);
@@ -1921,7 +1921,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
-static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
+static void fixup_rev1_53c810(struct pci_dev *dev)
{
/* rev 1 ncr53c810 chips don't set the class at all which means
* they don't get their resources remapped. Fix that here.
@@ -1935,7 +1935,7 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
/* Enable 1k I/O space granularity on the Intel P64H2 */
-static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
+static void quirk_p64h2_1k_io(struct pci_dev *dev)
{
u16 en1k;
@@ -1968,7 +1968,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap);
-static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
{
/*
* Disable PCI Bus Parking and PCI Master read caching on CX700
@@ -2031,7 +2031,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_c
* We believe that it is legal to read beyond the end tag and
* therefore the solution is to limit the read/write length.
*/
-static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
+static void quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
{
/*
* Only disable the VPD capability for 5706, 5706S, 5708,
@@ -2091,7 +2091,7 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_BROADCOM,
* the DRBs - this is where we expose device 6.
* http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
*/
-static void __devinit quirk_unhide_mch_dev6(struct pci_dev *dev)
+static void quirk_unhide_mch_dev6(struct pci_dev *dev)
{
u8 reg;
@@ -2115,7 +2115,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
* supports link speed auto negotiation, but falsely sets
* the link speed to 5GT/s.
*/
-static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
+static void quirk_tile_plx_gen1(struct pci_dev *dev)
{
if (tile_plx_gen1) {
pci_write_config_dword(dev, 0x98, 0x1);
@@ -2132,7 +2132,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
* aware of it. Instead of setting the flag on all busses in the
* machine, simply disable MSI globally.
*/
-static void __devinit quirk_disable_all_msi(struct pci_dev *dev)
+static void quirk_disable_all_msi(struct pci_dev *dev)
{
pci_no_msi();
dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
@@ -2146,7 +2146,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disab
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
-static void __devinit quirk_disable_msi(struct pci_dev *dev)
+static void quirk_disable_msi(struct pci_dev *dev)
{
if (dev->subordinate) {
dev_warn(&dev->dev, "MSI quirk detected; "
@@ -2164,7 +2164,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
* we use the possible vendor/device IDs of the host bridge for the
* declared quirk, and search for the APC bridge by slot number.
*/
-static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
+static void quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
{
struct pci_dev *apc_bridge;
@@ -2272,7 +2272,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
* for the MCP55 NIC. It is not yet determined whether the msi problem
* also affects other devices. As for now, turn off msi for this device.
*/
-static void __devinit nvenet_msi_disable(struct pci_dev *dev)
+static void nvenet_msi_disable(struct pci_dev *dev)
{
const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
@@ -2298,7 +2298,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
* we have it set correctly.
* Note this is an undocumented register.
*/
-static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
+static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
{
u32 cfg;
@@ -2534,11 +2534,11 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_q
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
-static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
+static void quirk_msi_intx_disable_bug(struct pci_dev *dev)
{
dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
}
-static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
{
struct pci_dev *p;
@@ -2612,7 +2612,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
* kernel fails to allocate resources when hotplug device is
* inserted and PCI bus is rescanned.
*/
-static void __devinit quirk_hotplug_bridge(struct pci_dev *dev)
+static void quirk_hotplug_bridge(struct pci_dev *dev)
{
dev->is_hotplug_bridge = 1;
}
@@ -2752,7 +2752,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
#endif
-static void __devinit fixup_ti816x_class(struct pci_dev* dev)
+static void fixup_ti816x_class(struct pci_dev *dev)
{
/* TI 816x devices do not have class code set when in PCIe boot mode */
dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
@@ -2764,7 +2764,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800,
/* Some PCIe devices do not work reliably with the claimed maximum
* payload size supported.
*/
-static void __devinit fixup_mpss_256(struct pci_dev *dev)
+static void fixup_mpss_256(struct pci_dev *dev)
{
dev->pcie_mpss = 1; /* 256 bytes */
}
@@ -2782,7 +2782,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
* coalescing must be disabled. Unfortunately, it cannot be re-enabled because
* it is possible to hotplug a device with MPS of 256B.
*/
-static void __devinit quirk_intel_mc_errata(struct pci_dev *dev)
+static void quirk_intel_mc_errata(struct pci_dev *dev)
{
int err;
u16 rcc;
@@ -2888,7 +2888,7 @@ static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
* This resolves crashes often seen on monitor unplug.
*/
#define I915_DEIER_REG 0x4400c
-static void __devinit disable_igfx_irq(struct pci_dev *dev)
+static void disable_igfx_irq(struct pci_dev *dev)
{
void __iomem *regs = pci_iomap(dev, 0, 0);
if (regs == NULL) {
@@ -2914,7 +2914,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
* PCI_COMMAND_INTX_DISABLE works though they actually do not properly
* support this feature.
*/
-static void __devinit quirk_broken_intx_masking(struct pci_dev *dev)
+static void quirk_broken_intx_masking(struct pci_dev *dev)
{
dev->broken_intx_masking = 1;
}
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 0aab85a51559..db542f4196a4 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -412,7 +412,7 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data)
return 0;
}
-static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
+static int pcifront_scan_bus(struct pcifront_device *pdev,
unsigned int domain, unsigned int bus,
struct pci_bus *b)
{
@@ -441,7 +441,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev,
return 0;
}
-static int __devinit pcifront_scan_root(struct pcifront_device *pdev,
+static int pcifront_scan_root(struct pcifront_device *pdev,
unsigned int domain, unsigned int bus)
{
struct pci_bus *b;
@@ -503,7 +503,7 @@ err_out:
return err;
}
-static int __devinit pcifront_rescan_root(struct pcifront_device *pdev,
+static int pcifront_rescan_root(struct pcifront_device *pdev,
unsigned int domain, unsigned int bus)
{
int err;
@@ -834,7 +834,7 @@ out:
return err;
}
-static int __devinit pcifront_try_connect(struct pcifront_device *pdev)
+static int pcifront_try_connect(struct pcifront_device *pdev)
{
int err = -EFAULT;
int i, num_roots, len;
@@ -924,7 +924,7 @@ out:
return err;
}
-static int __devinit pcifront_attach_devices(struct pcifront_device *pdev)
+static int pcifront_attach_devices(struct pcifront_device *pdev)
{
int err = -EFAULT;
int i, num_roots, len;
diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
index c2e997a570bf..0c6aac1232fc 100644
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -323,7 +323,7 @@ static struct pccard_operations bcm63xx_pcmcia_operations = {
/*
* register pcmcia socket to core
*/
-static int __devinit bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
{
struct bcm63xx_pcmcia_socket *skt;
struct pcmcia_socket *sock;
@@ -436,7 +436,7 @@ err:
return ret;
}
-static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
{
struct bcm63xx_pcmcia_socket *skt;
struct resource *res;
@@ -453,7 +453,7 @@ static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
struct platform_driver bcm63xx_pcmcia_driver = {
.probe = bcm63xx_drv_pcmcia_probe,
- .remove = __devexit_p(bcm63xx_drv_pcmcia_remove),
+ .remove = bcm63xx_drv_pcmcia_remove,
.driver = {
.name = "bcm63xx_pcmcia",
.owner = THIS_MODULE,
@@ -461,7 +461,7 @@ struct platform_driver bcm63xx_pcmcia_driver = {
};
#ifdef CONFIG_CARDBUS
-static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
+static int bcm63xx_cb_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
/* keep pci device */
@@ -469,7 +469,7 @@ static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
return platform_driver_register(&bcm63xx_pcmcia_driver);
}
-static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
+static void bcm63xx_cb_exit(struct pci_dev *dev)
{
platform_driver_unregister(&bcm63xx_pcmcia_driver);
bcm63xx_cb_dev = NULL;
@@ -503,7 +503,7 @@ static struct pci_driver bcm63xx_cardbus_driver = {
.name = "bcm63xx_cardbus",
.id_table = bcm63xx_cb_table,
.probe = bcm63xx_cb_probe,
- .remove = __devexit_p(bcm63xx_cb_exit),
+ .remove = bcm63xx_cb_exit,
};
#endif
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index ac1a2232eab9..ed3b522601b3 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -195,7 +195,7 @@ static struct pccard_operations bfin_cf_ops = {
/*--------------------------------------------------------------------------*/
-static int __devinit bfin_cf_probe(struct platform_device *pdev)
+static int bfin_cf_probe(struct platform_device *pdev)
{
struct bfin_cf_socket *cf;
struct resource *io_mem, *attr_mem;
@@ -286,7 +286,7 @@ fail0:
return status;
}
-static int __devexit bfin_cf_remove(struct platform_device *pdev)
+static int bfin_cf_remove(struct platform_device *pdev)
{
struct bfin_cf_socket *cf = platform_get_drvdata(pdev);
@@ -307,7 +307,7 @@ static struct platform_driver bfin_cf_driver = {
.owner = THIS_MODULE,
},
.probe = bfin_cf_probe,
- .remove = __devexit_p(bfin_cf_remove),
+ .remove = bfin_cf_remove,
};
module_platform_driver(bfin_cf_driver);
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index a484b1fb3382..a31e69ea99f3 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -409,7 +409,7 @@ static struct pccard_operations db1x_pcmcia_operations = {
.set_mem_map = au1x00_pcmcia_set_mem_map,
};
-static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
+static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
{
struct db1x_pcmcia_sock *sock;
struct resource *r;
@@ -559,7 +559,7 @@ out0:
return ret;
}
-static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
+static int db1x_pcmcia_socket_remove(struct platform_device *pdev)
{
struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
@@ -577,7 +577,7 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
.owner = THIS_MODULE,
},
.probe = db1x_pcmcia_socket_probe,
- .remove = __devexit_p(db1x_pcmcia_socket_remove),
+ .remove = db1x_pcmcia_socket_remove,
};
module_platform_driver(db1x_pcmcia_socket_driver);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 079629bff957..2deacbb2ffdc 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -920,8 +920,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
-#ifdef CONFIG_HOTPLUG
-
static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct pcmcia_device *p_dev;
@@ -962,15 +960,6 @@ static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
-#else
-
-static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return -ENODEV;
-}
-
-#endif
-
/************************ runtime PM support ***************************/
static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
@@ -1329,7 +1318,7 @@ static struct pcmcia_callback pcmcia_bus_callback = {
.resume = pcmcia_bus_resume,
};
-static int __devinit pcmcia_bus_add_socket(struct device *dev,
+static int pcmcia_bus_add_socket(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *socket = dev_get_drvdata(dev);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 7647d232e9e2..a007321ad314 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -181,7 +181,7 @@ static struct pccard_operations electra_cf_ops = {
.set_mem_map = electra_cf_set_mem_map,
};
-static int __devinit electra_cf_probe(struct platform_device *ofdev)
+static int electra_cf_probe(struct platform_device *ofdev)
{
struct device *device = &ofdev->dev;
struct device_node *np = ofdev->dev.of_node;
@@ -324,7 +324,7 @@ fail1:
}
-static int __devexit electra_cf_remove(struct platform_device *ofdev)
+static int electra_cf_remove(struct platform_device *ofdev)
{
struct device *device = &ofdev->dev;
struct electra_cf_socket *cf;
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 4e8831bdb6ef..3578e1ca97a0 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -35,7 +35,7 @@ static struct pci_driver i82092aa_pci_driver = {
.name = "i82092aa",
.id_table = i82092aa_pci_ids,
.probe = i82092aa_pci_probe,
- .remove = __devexit_p(i82092aa_pci_remove),
+ .remove = i82092aa_pci_remove,
};
@@ -67,7 +67,7 @@ static struct socket_info sockets[MAX_SOCKETS];
static int socket_count; /* shortcut */
-static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned char configbyte;
int i, ret;
@@ -162,7 +162,7 @@ err_out_disable:
return ret;
}
-static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
+static void i82092aa_pci_remove(struct pci_dev *dev)
{
struct pcmcia_socket *socket = pci_get_drvdata(dev);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 253e3867dec7..b29d97e170ae 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq)
return 0;
}
-static u_int __devinit pd6729_isa_scan(void)
+static u_int pd6729_isa_scan(void)
{
u_int mask0, mask = 0;
int i;
@@ -620,7 +620,7 @@ static u_int __devinit pd6729_isa_scan(void)
return mask;
}
-static int __devinit pd6729_pci_probe(struct pci_dev *dev,
+static int pd6729_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
int i, j, ret;
@@ -739,7 +739,7 @@ err_out_free_mem:
return ret;
}
-static void __devexit pd6729_pci_remove(struct pci_dev *dev)
+static void pd6729_pci_remove(struct pci_dev *dev)
{
int i;
struct pd6729_socket *socket = pci_get_drvdata(dev);
@@ -772,7 +772,7 @@ static struct pci_driver pd6729_pci_driver = {
.name = "pd6729",
.id_table = pd6729_pci_ids,
.probe = pd6729_pci_probe,
- .remove = __devexit_p(pd6729_pci_remove),
+ .remove = pd6729_pci_remove,
};
static int pd6729_module_init(void)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 7dd879ce514d..89ebd8c76636 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -208,7 +208,7 @@ static struct pcmcia_low_level sharpsl_pcmcia_ops = {
#ifdef CONFIG_SA1100_COLLIE
#include "sa11xx_base.h"
-int __devinit pcmcia_collie_init(struct device *dev)
+int pcmcia_collie_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 9da9656242af..430a9ac56091 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -1199,7 +1199,7 @@ static const struct attribute_group rsrc_attributes = {
.attrs = pccard_rsrc_attributes,
};
-static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
+static int pccard_sysfs_add_rsrc(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1209,7 +1209,7 @@ static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
return sysfs_create_group(&dev->kobj, &rsrc_attributes);
}
-static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
+static void pccard_sysfs_remove_rsrc(struct device *dev,
struct class_interface *class_intf)
{
struct pcmcia_socket *s = dev_get_drvdata(dev);
@@ -1222,7 +1222,7 @@ static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
static struct class_interface pccard_rsrc_interface __refdata = {
.class = &pcmcia_socket_class,
.add_dev = &pccard_sysfs_add_rsrc,
- .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
+ .remove_dev = &pccard_sysfs_remove_rsrc,
};
static int __init nonstatic_sysfs_init(void)
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index ba8557eea618..44cfc4416e54 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -95,7 +95,7 @@ static struct pcmcia_low_level assabet_pcmcia_ops = {
.socket_suspend = assabet_pcmcia_socket_suspend,
};
-int __devinit pcmcia_assabet_init(struct device *dev)
+int pcmcia_assabet_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index c59c44921a3a..b3774e5d0396 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -81,7 +81,7 @@ static struct pcmcia_low_level cerf_pcmcia_ops = {
.configure_socket = cerf_pcmcia_configure_socket,
};
-int __devinit pcmcia_cerf_init(struct device *dev)
+int pcmcia_cerf_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 2eea664bc079..ff8a027a4afb 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -43,7 +43,7 @@
int __init pcmcia_collie_init(struct device *dev);
-static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
+static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_init,
#endif
@@ -67,7 +67,7 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) __devinitdata = {
#endif
};
-static int __devinit sa11x0_drv_pcmcia_probe(struct platform_device *dev)
+static int sa11x0_drv_pcmcia_probe(struct platform_device *dev)
{
int i, ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index d9c7337b909c..431d8b07cbaf 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -153,7 +153,7 @@ struct pcmcia_low_level h3600_pcmcia_ops = {
.socket_suspend = h3600_pcmcia_socket_suspend,
};
-int __devinit pcmcia_h3600_init(struct device *dev)
+int pcmcia_h3600_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index 56ab73915602..b07a2dc3296e 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -92,7 +92,7 @@ static struct pcmcia_low_level shannon_pcmcia_ops = {
.configure_socket = shannon_pcmcia_configure_socket,
};
-int __devinit pcmcia_shannon_init(struct device *dev)
+int pcmcia_shannon_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index 8647b17c449e..73fd37968b6a 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -109,7 +109,7 @@ static struct pcmcia_low_level simpad_pcmcia_ops = {
.socket_suspend = simpad_pcmcia_socket_suspend,
};
-int __devinit pcmcia_simpad_init(struct device *dev)
+int pcmcia_simpad_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 70f728ce1856..65b02c3e14ce 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -211,7 +211,7 @@ static int pcmcia_probe(struct sa1111_dev *dev)
return 0;
}
-static int __devexit pcmcia_remove(struct sa1111_dev *dev)
+static int pcmcia_remove(struct sa1111_dev *dev)
{
struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
@@ -234,7 +234,7 @@ static struct sa1111_driver pcmcia_driver = {
},
.devid = SA1111_DEVID_PCMCIA,
.probe = pcmcia_probe,
- .remove = __devexit_p(pcmcia_remove),
+ .remove = pcmcia_remove,
};
static int __init sa1111_drv_pcmcia_init(void)
diff --git a/drivers/pcmcia/sa1111_jornada720.c b/drivers/pcmcia/sa1111_jornada720.c
index 69428d1f5ae1..3baa3ef09682 100644
--- a/drivers/pcmcia/sa1111_jornada720.c
+++ b/drivers/pcmcia/sa1111_jornada720.c
@@ -91,7 +91,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
.nr = 2,
};
-int __devinit pcmcia_jornada720_init(struct device *dev)
+int pcmcia_jornada720_init(struct device *dev)
{
int ret = -ENODEV;
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 86e4a1a3c642..75806be344e5 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -564,7 +564,7 @@ static inline void reserve_using_irq(int slot)
vrc4171_irq_mask &= ~(1 << irq);
}
-static int __devinit vrc4171_add_sockets(void)
+static int vrc4171_add_sockets(void)
{
vrc4171_socket_t *socket;
int slot, retval;
@@ -631,7 +631,7 @@ static void vrc4171_remove_sockets(void)
}
}
-static int __devinit vrc4171_card_setup(char *options)
+static int vrc4171_card_setup(char *options)
{
if (options == NULL || *options == '\0')
return 1;
@@ -712,7 +712,7 @@ static struct platform_driver vrc4171_card_driver = {
},
};
-static int __devinit vrc4171_card_init(void)
+static int vrc4171_card_init(void)
{
int retval;
@@ -746,7 +746,7 @@ static int __devinit vrc4171_card_init(void)
return 0;
}
-static void __devexit vrc4171_card_exit(void)
+static void vrc4171_card_exit(void)
{
free_irq(vrc4171_irq, vrc4171_sockets);
vrc4171_remove_sockets();
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index cd0a315d922b..d92692056e24 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -456,7 +456,7 @@ static void cardu_interrupt(int irq, void *dev_id)
}
}
-static int __devinit vrc4173_cardu_probe(struct pci_dev *dev,
+static int vrc4173_cardu_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
vrc4173_socket_t *socket;
@@ -533,7 +533,7 @@ disable:
return ret;
}
-static int __devinit vrc4173_cardu_setup(char *options)
+static int vrc4173_cardu_setup(char *options)
{
if (options == NULL || *options == '\0')
return 1;
@@ -574,14 +574,14 @@ static struct pci_driver vrc4173_cardu_driver = {
.id_table = vrc4173_cardu_id_table,
};
-static int __devinit vrc4173_cardu_init(void)
+static int vrc4173_cardu_init(void)
{
vrc4173_cardu_slots = 0;
return pci_register_driver(&vrc4173_cardu_driver);
}
-static void __devexit vrc4173_cardu_exit(void)
+static void vrc4173_cardu_exit(void)
{
pci_unregister_driver(&vrc4173_cardu_driver);
}
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index fd5fbd10aad0..95f5b270ad44 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -204,7 +204,7 @@ static struct pccard_operations xxs1500_pcmcia_operations = {
.set_mem_map = au1x00_pcmcia_set_mem_map,
};
-static int __devinit xxs1500_pcmcia_probe(struct platform_device *pdev)
+static int xxs1500_pcmcia_probe(struct platform_device *pdev)
{
struct xxs1500_pcmcia_sock *sock;
struct resource *r;
@@ -299,7 +299,7 @@ out0:
return ret;
}
-static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
+static int xxs1500_pcmcia_remove(struct platform_device *pdev)
{
struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
@@ -317,7 +317,7 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
.owner = THIS_MODULE,
},
.probe = xxs1500_pcmcia_probe,
- .remove = __devexit_p(xxs1500_pcmcia_remove),
+ .remove = xxs1500_pcmcia_remove,
};
module_platform_driver(xxs1500_pcmcia_socket_driver);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 667678db1153..6b4ff099fb13 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -783,7 +783,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
/*
* Close it down - release our resources and go home..
*/
-static void __devexit yenta_close(struct pci_dev *dev)
+static void yenta_close(struct pci_dev *dev)
{
struct yenta_socket *sock = pci_get_drvdata(dev);
@@ -1142,7 +1142,7 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
* interrupt, and that we can map the cardbus area. Fill in the
* socket information structure..
*/
-static int __devinit yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
+static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct yenta_socket *socket;
int ret;
@@ -1435,7 +1435,7 @@ static struct pci_driver yenta_cardbus_driver = {
.name = "yenta_cardbus",
.id_table = yenta_table,
.probe = yenta_probe,
- .remove = __devexit_p(yenta_close),
+ .remove = yenta_close,
.driver.pm = YENTA_PM_OPS,
};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index d96caefd914a..390ab69ea569 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -26,6 +26,15 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+config PINCTRL_AT91
+ bool "AT91 pinctrl driver"
+ depends on OF
+ depends on ARCH_AT91
+ select PINMUX
+ select PINCONF
+ help
+ Say Y here to enable the at91 pinctrl driver
+
config PINCTRL_BCM2835
bool
select PINMUX
@@ -87,21 +96,18 @@ config PINCTRL_MMP2
bool "MMP2 pin controller driver"
depends on ARCH_MMP
select PINCTRL_PXA3xx
- select PINCONF
config PINCTRL_MXS
bool
+ select PINMUX
+ select PINCONF
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
@@ -126,13 +132,11 @@ config PINCTRL_PXA168
bool "PXA168 pin controller driver"
depends on ARCH_MMP
select PINCTRL_PXA3xx
- select PINCONF
config PINCTRL_PXA910
bool "PXA910 pin controller driver"
depends on ARCH_MMP
select PINCTRL_PXA3xx
- select PINCONF
config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
@@ -143,23 +147,21 @@ config PINCTRL_SINGLE
This selects the device tree based generic pinctrl driver.
config PINCTRL_SIRF
- bool "CSR SiRFprimaII pin controller driver"
- depends on ARCH_PRIMA2
+ bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
+ depends on ARCH_SIRF
select PINMUX
config PINCTRL_TEGRA
bool
+ select PINMUX
+ select PINCONF
config PINCTRL_TEGRA20
bool
- select PINMUX
- select PINCONF
select PINCTRL_TEGRA
config PINCTRL_TEGRA30
bool
- select PINMUX
- select PINCONF
select PINCTRL_TEGRA
config PINCTRL_U300
@@ -178,7 +180,7 @@ config PINCTRL_COH901
ports of 8 GPIO pins each.
config PINCTRL_SAMSUNG
- bool "Samsung pinctrl driver"
+ bool
depends on OF && GPIOLIB
select PINMUX
select PINCONF
@@ -188,27 +190,7 @@ config PINCTRL_EXYNOS4
depends on OF && GPIOLIB
select PINCTRL_SAMSUNG
-config PINCTRL_MVEBU
- bool
- depends on ARCH_MVEBU
- select PINMUX
- select PINCONF
-
-config PINCTRL_DOVE
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_KIRKWOOD
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_370
- bool
- select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_XP
- bool
- select PINCTRL_MVEBU
+source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f395ba5cec25..f95f5ed923be 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,6 +9,7 @@ ifeq ($(CONFIG_OF),y)
obj-$(CONFIG_PINCTRL) += devicetree.o
endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
+obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
obj-$(CONFIG_PINCTRL_IMX) += pinctrl-imx.o
obj-$(CONFIG_PINCTRL_IMX35) += pinctrl-imx35.o
@@ -36,12 +37,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
-obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
-obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
-obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
-obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
+obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2e39c04fc16b..5cdee8669ea3 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -345,6 +345,62 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
+struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+ struct pinctrl_gpio_range *range)
+{
+ struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+
+ /*
+ * If we can't find this device, let's assume that is because
+ * it has not probed yet, so the driver trying to register this
+ * range need to defer probing.
+ */
+ if (!pctldev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ pinctrl_add_gpio_range(pctldev, range);
+ return pctldev;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
+
+/**
+ * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
+ * @pctldev: the pin controller device to look in
+ * @pin: a controller-local number to find the range for
+ */
+struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+ unsigned int pin)
+{
+ struct pinctrl_gpio_range *range = NULL;
+
+ /* Loop over the ranges */
+ list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+ /* Check if we're in the valid range */
+ if (pin >= range->pin_base &&
+ pin < range->pin_base + range->npins) {
+ return range;
+ }
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
+
+/**
+ * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
+ * @pctldev: pin controller device to remove the range from
+ * @range: the GPIO range to remove
+ */
+void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range)
+{
+ mutex_lock(&pinctrl_mutex);
+ list_del(&range->node);
+ mutex_unlock(&pinctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
+
/**
* pinctrl_get_group_selector() - returns the group selector for a group
* @pctldev: the pin controller handling the group
@@ -563,6 +619,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -EPROBE_DEFER;
}
+ setting->dev_name = map->dev_name;
+
switch (map->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_map_to_setting(map, setting);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 1f40ff68a8c4..12f5694f3d5d 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
* @type: the type of setting
* @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE.
+ * @dev_name: the name of the device using this state
* @data: Data specific to the setting type
*/
struct pinctrl_setting {
struct list_head node;
enum pinctrl_map_type type;
struct pinctrl_dev *pctldev;
+ const char *dev_name;
union {
struct pinctrl_setting_mux mux;
struct pinctrl_setting_configs configs;
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fcb1de45473c..fe2d1af7cfa0 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
return NULL;
}
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+ struct pinctrl_dev *pctldev;
+
+ pctldev = find_pinctrl_by_of_node(np);
+ if (!pctldev)
+ return NULL;
+
+ return pctldev;
+}
+
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config)
{
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
new file mode 100644
index 000000000000..366fa541ee91
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -0,0 +1,24 @@
+if PLAT_ORION
+
+config PINCTRL_MVEBU
+ bool
+ select PINMUX
+ select PINCONF
+
+config PINCTRL_DOVE
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+ bool
+ select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+ bool
+ select PINCTRL_MVEBU
+
+endif
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
new file mode 100644
index 000000000000..37c253297af0
--- /dev/null
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index c907647de6ad..c907647de6ad 100644
--- a/drivers/pinctrl/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index 40bd52a46b4e..40bd52a46b4e 100644
--- a/drivers/pinctrl/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index ffe74b27d66d..ffe74b27d66d 100644
--- a/drivers/pinctrl/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 9a74ef674a0e..9a74ef674a0e 100644
--- a/drivers/pinctrl/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 8e6266c6249a..6c44b7e8964c 100644
--- a/drivers/pinctrl/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -24,7 +24,6 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include "core.h"
#include "pinctrl-mvebu.h"
#define MPPS_PER_REG 8
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
index 90bd3beee860..90bd3beee860 100644
--- a/drivers/pinctrl/pinctrl-mvebu.h
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 33fbaeaa65dd..833a36458157 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -41,6 +41,7 @@ struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
+ PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_DISABLE, "input schmitt disabled", NULL),
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
new file mode 100644
index 000000000000..c5e757157183
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -0,0 +1,1634 @@
+/*
+ * at91 pinctrl driver based on at91 pinmux core
+ *
+ * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+/* Since we request GPIOs from ourself */
+#include <linux/pinctrl/consumer.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/at91_pio.h>
+
+#include "core.h"
+
+#define MAX_NB_GPIO_PER_BANK 32
+
+struct at91_pinctrl_mux_ops;
+
+struct at91_gpio_chip {
+ struct gpio_chip chip;
+ struct pinctrl_gpio_range range;
+ struct at91_gpio_chip *next; /* Bank sharing same clock */
+ int pioc_hwirq; /* PIO bank interrupt identifier on AIC */
+ int pioc_virq; /* PIO bank Linux virtual interrupt */
+ int pioc_idx; /* PIO bank index */
+ void __iomem *regbase; /* PIO bank virtual address */
+ struct clk *clock; /* associated clock */
+ struct irq_domain *domain; /* associated irq domain */
+ struct at91_pinctrl_mux_ops *ops; /* ops */
+};
+
+#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
+
+static struct at91_gpio_chip *gpio_chips[MAX_GPIO_BANKS];
+
+static int gpio_banks;
+
+#define PULL_UP (1 << 0)
+#define MULTI_DRIVE (1 << 1)
+#define DEGLITCH (1 << 2)
+#define PULL_DOWN (1 << 3)
+#define DIS_SCHMIT (1 << 4)
+#define DEBOUNCE (1 << 16)
+#define DEBOUNCE_VAL_SHIFT 17
+#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
+
+/**
+ * struct at91_pmx_func - describes AT91 pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @ngroups: the number of groups
+ */
+struct at91_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+enum at91_mux {
+ AT91_MUX_GPIO = 0,
+ AT91_MUX_PERIPH_A = 1,
+ AT91_MUX_PERIPH_B = 2,
+ AT91_MUX_PERIPH_C = 3,
+ AT91_MUX_PERIPH_D = 4,
+};
+
+/**
+ * struct at91_pmx_pin - describes an At91 pin mux
+ * @bank: the bank of the pin
+ * @pin: the pin number in the @bank
+ * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function.
+ * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
+ */
+struct at91_pmx_pin {
+ uint32_t bank;
+ uint32_t pin;
+ enum at91_mux mux;
+ unsigned long conf;
+};
+
+/**
+ * struct at91_pin_group - describes an At91 pin group
+ * @name: the name of this specific pin group
+ * @pins_conf: the mux mode for each pin in this group. The size of this
+ * array is the same as pins.
+ * @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
+ */
+struct at91_pin_group {
+ const char *name;
+ struct at91_pmx_pin *pins_conf;
+ unsigned int *pins;
+ unsigned npins;
+};
+
+/**
+ * struct at91_pinctrl_mux_ops - describes an At91 mux ops group
+ * on new IP with support for periph C and D the way to mux in
+ * periph A and B has changed
+ * So provide the right call back
+ * if not present means the IP does not support it
+ * @get_periph: return the periph mode configured
+ * @mux_A_periph: mux as periph A
+ * @mux_B_periph: mux as periph B
+ * @mux_C_periph: mux as periph C
+ * @mux_D_periph: mux as periph D
+ * @get_deglitch: get deglitch status
+ * @set_deglitch: enable/disable deglitch
+ * @get_debounce: get debounce status
+ * @set_debounce: enable/disable debounce
+ * @get_pulldown: get pulldown status
+ * @set_pulldown: enable/disable pulldown
+ * @get_schmitt_trig: get schmitt trigger status
+ * @disable_schmitt_trig: disable schmitt trigger
+ * @irq_type: return irq type
+ */
+struct at91_pinctrl_mux_ops {
+ enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask);
+ void (*mux_A_periph)(void __iomem *pio, unsigned mask);
+ void (*mux_B_periph)(void __iomem *pio, unsigned mask);
+ void (*mux_C_periph)(void __iomem *pio, unsigned mask);
+ void (*mux_D_periph)(void __iomem *pio, unsigned mask);
+ bool (*get_deglitch)(void __iomem *pio, unsigned pin);
+ void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
+ bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
+ void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
+ bool (*get_pulldown)(void __iomem *pio, unsigned pin);
+ void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
+ bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
+ void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
+ /* irq */
+ int (*irq_type)(struct irq_data *d, unsigned type);
+};
+
+static int gpio_irq_type(struct irq_data *d, unsigned type);
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type);
+
+struct at91_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+
+ int nbanks;
+
+ uint32_t *mux_mask;
+ int nmux;
+
+ struct at91_pmx_func *functions;
+ int nfunctions;
+
+ struct at91_pin_group *groups;
+ int ngroups;
+
+ struct at91_pinctrl_mux_ops *ops;
+};
+
+static const inline struct at91_pin_group *at91_pinctrl_find_group_by_name(
+ const struct at91_pinctrl *info,
+ const char *name)
+{
+ const struct at91_pin_group *grp = NULL;
+ int i;
+
+ for (i = 0; i < info->ngroups; i++) {
+ if (strcmp(info->groups[i].name, name))
+ continue;
+
+ grp = &info->groups[i];
+ dev_dbg(info->dev, "%s: %d 0:%d\n", name, grp->npins, grp->pins[0]);
+ break;
+ }
+
+ return grp;
+}
+
+static int at91_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->ngroups;
+}
+
+static const char *at91_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->groups[selector].name;
+}
+
+static int at91_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *npins)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->groups[selector].pins;
+ *npins = info->groups[selector].npins;
+
+ return 0;
+}
+
+static void at91_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct at91_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 = at91_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;
+ }
+
+ map_num += grp->npins;
+ new_map = devm_kzalloc(pctldev->dev, sizeof(*new_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) {
+ kfree(new_map);
+ 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++) {
+ 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->pins_conf[i].conf;
+ new_map[i].data.configs.num_configs = 1;
+ }
+
+ dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+ (*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+ return 0;
+}
+
+static void at91_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+}
+
+static struct pinctrl_ops at91_pctrl_ops = {
+ .get_groups_count = at91_get_groups_count,
+ .get_group_name = at91_get_group_name,
+ .get_group_pins = at91_get_group_pins,
+ .pin_dbg_show = at91_pin_dbg_show,
+ .dt_node_to_map = at91_dt_node_to_map,
+ .dt_free_map = at91_dt_free_map,
+};
+
+static void __iomem * pin_to_controller(struct at91_pinctrl *info,
+ unsigned int bank)
+{
+ return gpio_chips[bank]->regbase;
+}
+
+static inline int pin_to_bank(unsigned pin)
+{
+ return pin /= MAX_NB_GPIO_PER_BANK;
+}
+
+static unsigned pin_to_mask(unsigned int pin)
+{
+ return 1 << pin;
+}
+
+static void at91_mux_disable_interrupt(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static unsigned at91_mux_get_pullup(void __iomem *pio, unsigned pin)
+{
+ return (readl_relaxed(pio + PIO_PUSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
+{
+ writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
+}
+
+static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
+{
+ return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_multidrive(void __iomem *pio, unsigned mask, bool on)
+{
+ writel_relaxed(mask, pio + (on ? PIO_MDER : PIO_MDDR));
+}
+
+static void at91_mux_set_A_periph(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(mask, pio + PIO_ASR);
+}
+
+static void at91_mux_set_B_periph(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(mask, pio + PIO_BSR);
+}
+
+static void at91_mux_pio3_set_A_periph(void __iomem *pio, unsigned mask)
+{
+
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask,
+ pio + PIO_ABCDSR1);
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+ pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_B_periph(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask,
+ pio + PIO_ABCDSR1);
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) & ~mask,
+ pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_C_periph(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static void at91_mux_pio3_set_D_periph(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
+ writel_relaxed(readl_relaxed(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
+}
+
+static enum at91_mux at91_mux_pio3_get_periph(void __iomem *pio, unsigned mask)
+{
+ unsigned select;
+
+ if (readl_relaxed(pio + PIO_PSR) & mask)
+ return AT91_MUX_GPIO;
+
+ select = !!(readl_relaxed(pio + PIO_ABCDSR1) & mask);
+ select |= (!!(readl_relaxed(pio + PIO_ABCDSR2) & mask) << 1);
+
+ return select + 1;
+}
+
+static enum at91_mux at91_mux_get_periph(void __iomem *pio, unsigned mask)
+{
+ unsigned select;
+
+ if (readl_relaxed(pio + PIO_PSR) & mask)
+ return AT91_MUX_GPIO;
+
+ select = readl_relaxed(pio + PIO_ABSR) & mask;
+
+ return select + 1;
+}
+
+static bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
+{
+ return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+ __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+}
+
+static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+ if (is_on)
+ __raw_writel(mask, pio + PIO_IFSCDR);
+ at91_mux_set_deglitch(pio, mask, is_on);
+}
+
+static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
+{
+ *div = __raw_readl(pio + PIO_SCDR);
+
+ return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
+ bool is_on, u32 div)
+{
+ if (is_on) {
+ __raw_writel(mask, pio + PIO_IFSCER);
+ __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
+ __raw_writel(mask, pio + PIO_IFER);
+ } else {
+ __raw_writel(mask, pio + PIO_IFDR);
+ }
+}
+
+static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
+{
+ return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
+{
+ __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
+}
+
+static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
+{
+ __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
+}
+
+static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
+{
+ return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
+}
+
+static struct at91_pinctrl_mux_ops at91rm9200_ops = {
+ .get_periph = at91_mux_get_periph,
+ .mux_A_periph = at91_mux_set_A_periph,
+ .mux_B_periph = at91_mux_set_B_periph,
+ .get_deglitch = at91_mux_get_deglitch,
+ .set_deglitch = at91_mux_set_deglitch,
+ .irq_type = gpio_irq_type,
+};
+
+static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
+ .get_periph = at91_mux_pio3_get_periph,
+ .mux_A_periph = at91_mux_pio3_set_A_periph,
+ .mux_B_periph = at91_mux_pio3_set_B_periph,
+ .mux_C_periph = at91_mux_pio3_set_C_periph,
+ .mux_D_periph = at91_mux_pio3_set_D_periph,
+ .get_deglitch = at91_mux_get_deglitch,
+ .set_deglitch = at91_mux_pio3_set_deglitch,
+ .get_debounce = at91_mux_pio3_get_debounce,
+ .set_debounce = at91_mux_pio3_set_debounce,
+ .get_pulldown = at91_mux_pio3_get_pulldown,
+ .set_pulldown = at91_mux_pio3_set_pulldown,
+ .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+ .irq_type = alt_gpio_irq_type,
+};
+
+static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
+{
+ if (pin->mux) {
+ dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
+ pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
+ } else {
+ dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
+ pin->bank + 'A', pin->pin, pin->conf);
+ }
+}
+
+static int pin_check_config(struct at91_pinctrl *info, const char* name,
+ int index, const struct at91_pmx_pin *pin)
+{
+ int mux;
+
+ /* check if it's a valid config */
+ if (pin->bank >= info->nbanks) {
+ dev_err(info->dev, "%s: pin conf %d bank_id %d >= nbanks %d\n",
+ name, index, pin->bank, info->nbanks);
+ return -EINVAL;
+ }
+
+ if (pin->pin >= MAX_NB_GPIO_PER_BANK) {
+ dev_err(info->dev, "%s: pin conf %d pin_bank_id %d >= %d\n",
+ name, index, pin->pin, MAX_NB_GPIO_PER_BANK);
+ return -EINVAL;
+ }
+
+ if (!pin->mux)
+ return 0;
+
+ mux = pin->mux - 1;
+
+ if (mux >= info->nmux) {
+ dev_err(info->dev, "%s: pin conf %d mux_id %d >= nmux %d\n",
+ name, index, mux, info->nmux);
+ return -EINVAL;
+ }
+
+ if (!(info->mux_mask[pin->bank * info->nmux + mux] & 1 << pin->pin)) {
+ dev_err(info->dev, "%s: pin conf %d mux_id %d not supported for pio%c%d\n",
+ name, index, mux, pin->bank + 'A', pin->pin);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void at91_mux_gpio_disable(void __iomem *pio, unsigned mask)
+{
+ writel_relaxed(mask, pio + PIO_PDR);
+}
+
+static void at91_mux_gpio_enable(void __iomem *pio, unsigned mask, bool input)
+{
+ writel_relaxed(mask, pio + PIO_PER);
+ writel_relaxed(mask, pio + (input ? PIO_ODR : PIO_OER));
+}
+
+static int at91_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+ const struct at91_pmx_pin *pin;
+ uint32_t npins = info->groups[group].npins;
+ int i, ret;
+ unsigned mask;
+ void __iomem *pio;
+
+ dev_dbg(info->dev, "enable function %s group %s\n",
+ info->functions[selector].name, info->groups[group].name);
+
+ /* first check that all the pins of the group are valid with a valid
+ * paramter */
+ for (i = 0; i < npins; i++) {
+ pin = &pins_conf[i];
+ ret = pin_check_config(info, info->groups[group].name, i, pin);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < npins; i++) {
+ pin = &pins_conf[i];
+ at91_pin_dbg(info->dev, pin);
+ pio = pin_to_controller(info, pin->bank);
+ mask = pin_to_mask(pin->pin);
+ at91_mux_disable_interrupt(pio, mask);
+ switch(pin->mux) {
+ case AT91_MUX_GPIO:
+ at91_mux_gpio_enable(pio, mask, 1);
+ break;
+ case AT91_MUX_PERIPH_A:
+ info->ops->mux_A_periph(pio, mask);
+ break;
+ case AT91_MUX_PERIPH_B:
+ info->ops->mux_B_periph(pio, mask);
+ break;
+ case AT91_MUX_PERIPH_C:
+ if (!info->ops->mux_C_periph)
+ return -EINVAL;
+ info->ops->mux_C_periph(pio, mask);
+ break;
+ case AT91_MUX_PERIPH_D:
+ if (!info->ops->mux_D_periph)
+ return -EINVAL;
+ info->ops->mux_D_periph(pio, mask);
+ break;
+ }
+ if (pin->mux)
+ at91_mux_gpio_disable(pio, mask);
+ }
+
+ return 0;
+}
+
+static void at91_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ const struct at91_pmx_pin *pins_conf = info->groups[group].pins_conf;
+ const struct at91_pmx_pin *pin;
+ uint32_t npins = info->groups[group].npins;
+ int i;
+ unsigned mask;
+ void __iomem *pio;
+
+ for (i = 0; i < npins; i++) {
+ pin = &pins_conf[i];
+ at91_pin_dbg(info->dev, pin);
+ pio = pin_to_controller(info, pin->bank);
+ mask = pin_to_mask(pin->pin);
+ at91_mux_gpio_enable(pio, mask, 1);
+ }
+}
+
+static int at91_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->nfunctions;
+}
+
+static const char *at91_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ return info->functions[selector].name;
+}
+
+static int at91_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = info->functions[selector].groups;
+ *num_groups = info->functions[selector].ngroups;
+
+ return 0;
+}
+
+static int at91_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct at91_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ struct at91_gpio_chip *at91_chip;
+ struct gpio_chip *chip;
+ unsigned mask;
+
+ 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;
+ at91_chip = container_of(chip, struct at91_gpio_chip, chip);
+
+ dev_dbg(npct->dev, "enable pin %u as GPIO\n", offset);
+
+ mask = 1 << (offset - chip->base);
+
+ dev_dbg(npct->dev, "enable pin %u as PIO%c%d 0x%x\n",
+ offset, 'A' + range->id, offset - chip->base, mask);
+
+ writel_relaxed(mask, at91_chip->regbase + PIO_PER);
+
+ return 0;
+}
+
+static void at91_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned offset)
+{
+ struct at91_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 at91_pmx_ops = {
+ .get_functions_count = at91_pmx_get_funcs_count,
+ .get_function_name = at91_pmx_get_func_name,
+ .get_function_groups = at91_pmx_get_groups,
+ .enable = at91_pmx_enable,
+ .disable = at91_pmx_disable,
+ .gpio_request_enable = at91_gpio_request_enable,
+ .gpio_disable_free = at91_gpio_disable_free,
+};
+
+static int at91_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *config)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ void __iomem *pio;
+ unsigned pin;
+ int div;
+
+ dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, *config);
+ pio = pin_to_controller(info, pin_to_bank(pin_id));
+ pin = pin_id % MAX_NB_GPIO_PER_BANK;
+
+ if (at91_mux_get_multidrive(pio, pin))
+ *config |= MULTI_DRIVE;
+
+ if (at91_mux_get_pullup(pio, pin))
+ *config |= PULL_UP;
+
+ if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin))
+ *config |= DEGLITCH;
+ if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
+ *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+ if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
+ *config |= PULL_DOWN;
+ if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
+ *config |= DIS_SCHMIT;
+
+ return 0;
+}
+
+static int at91_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long config)
+{
+ struct at91_pinctrl *info = pinctrl_dev_get_drvdata(pctldev);
+ unsigned mask;
+ void __iomem *pio;
+
+ dev_dbg(info->dev, "%s:%d, pin_id=%d, config=0x%lx", __func__, __LINE__, pin_id, config);
+ pio = pin_to_controller(info, pin_to_bank(pin_id));
+ mask = pin_to_mask(pin_id % MAX_NB_GPIO_PER_BANK);
+
+ if (config & PULL_UP && config & PULL_DOWN)
+ return -EINVAL;
+
+ at91_mux_set_pullup(pio, mask, config & PULL_UP);
+ at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
+ if (info->ops->set_deglitch)
+ info->ops->set_deglitch(pio, mask, config & DEGLITCH);
+ if (info->ops->set_debounce)
+ info->ops->set_debounce(pio, mask, config & DEBOUNCE,
+ (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+ if (info->ops->set_pulldown)
+ info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
+ if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
+ info->ops->disable_schmitt_trig(pio, mask);
+
+ return 0;
+}
+
+static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+
+}
+
+static void at91_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned group)
+{
+}
+
+static struct pinconf_ops at91_pinconf_ops = {
+ .pin_config_get = at91_pinconf_get,
+ .pin_config_set = at91_pinconf_set,
+ .pin_config_dbg_show = at91_pinconf_dbg_show,
+ .pin_config_group_dbg_show = at91_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc at91_pinctrl_desc = {
+ .pctlops = &at91_pctrl_ops,
+ .pmxops = &at91_pmx_ops,
+ .confops = &at91_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const char *gpio_compat = "atmel,at91rm9200-gpio";
+
+static void __devinit at91_pinctrl_child_count(struct at91_pinctrl *info,
+ struct device_node *np)
+{
+ struct device_node *child;
+
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat)) {
+ info->nbanks++;
+ } else {
+ info->nfunctions++;
+ info->ngroups += of_get_child_count(child);
+ }
+ }
+}
+
+static int __devinit at91_pinctrl_mux_mask(struct at91_pinctrl *info,
+ struct device_node *np)
+{
+ int ret = 0;
+ int size;
+ const const __be32 *list;
+
+ list = of_get_property(np, "atmel,mux-mask", &size);
+ if (!list) {
+ dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+ return -EINVAL;
+ }
+
+ size /= sizeof(*list);
+ if (!size || size % info->nbanks) {
+ dev_err(info->dev, "wrong mux mask array should be by %d\n", info->nbanks);
+ return -EINVAL;
+ }
+ info->nmux = size / info->nbanks;
+
+ info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
+ if (!info->mux_mask) {
+ dev_err(info->dev, "could not alloc mux_mask\n");
+ return -ENOMEM;
+ }
+
+ ret = of_property_read_u32_array(np, "atmel,mux-mask",
+ info->mux_mask, size);
+ if (ret)
+ dev_err(info->dev, "can not read the mux-mask of %d\n", size);
+ return ret;
+}
+
+static int __devinit at91_pinctrl_parse_groups(struct device_node *np,
+ struct at91_pin_group *grp,
+ struct at91_pinctrl *info,
+ u32 index)
+{
+ struct at91_pmx_pin *pin;
+ int size;
+ const const __be32 *list;
+ int i, j;
+
+ dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+ /* Initialise group */
+ grp->name = np->name;
+
+ /*
+ * the binding format is atmel,pins = <bank pin mux CONFIG ...>,
+ * do sanity check and calculate pins number
+ */
+ list = of_get_property(np, "atmel,pins", &size);
+ /* we do not check return since it's safe node passed down */
+ size /= sizeof(*list);
+ if (!size || size % 4) {
+ dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n");
+ return -EINVAL;
+ }
+
+ grp->npins = size / 4;
+ pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin),
+ GFP_KERNEL);
+ grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!grp->pins_conf || !grp->pins)
+ return -ENOMEM;
+
+ for (i = 0, j = 0; i < size; i += 4, j++) {
+ pin->bank = be32_to_cpu(*list++);
+ pin->pin = be32_to_cpu(*list++);
+ grp->pins[j] = pin->bank * MAX_NB_GPIO_PER_BANK + pin->pin;
+ pin->mux = be32_to_cpu(*list++);
+ pin->conf = be32_to_cpu(*list++);
+
+ at91_pin_dbg(info->dev, pin);
+ pin++;
+ }
+
+ return 0;
+}
+
+static int __devinit at91_pinctrl_parse_functions(struct device_node *np,
+ struct at91_pinctrl *info, u32 index)
+{
+ struct device_node *child;
+ struct at91_pmx_func *func;
+ struct at91_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->ngroups = of_get_child_count(np);
+ if (func->ngroups <= 0) {
+ dev_err(info->dev, "no groups defined\n");
+ return -EINVAL;
+ }
+ func->groups = devm_kzalloc(info->dev,
+ func->ngroups * sizeof(char *), GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;
+
+ for_each_child_of_node(np, child) {
+ func->groups[i] = child->name;
+ grp = &info->groups[grp_index++];
+ ret = at91_pinctrl_parse_groups(child, grp, info, i++);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct of_device_id at91_pinctrl_of_match[] __devinitdata = {
+ { .compatible = "atmel,at91sam9x5-pinctrl", .data = &at91sam9x5_ops },
+ { .compatible = "atmel,at91rm9200-pinctrl", .data = &at91rm9200_ops },
+ { /* sentinel */ }
+};
+
+static int __devinit at91_pinctrl_probe_dt(struct platform_device *pdev,
+ struct at91_pinctrl *info)
+{
+ int ret = 0;
+ int i, j;
+ uint32_t *tmp;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+
+ if (!np)
+ return -ENODEV;
+
+ info->dev = &pdev->dev;
+ info->ops = (struct at91_pinctrl_mux_ops*)
+ of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
+ at91_pinctrl_child_count(info, np);
+
+ if (info->nbanks < 1) {
+ dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+ return -EINVAL;
+ }
+
+ ret = at91_pinctrl_mux_mask(info, np);
+ if (ret)
+ return ret;
+
+ dev_dbg(&pdev->dev, "nmux = %d\n", info->nmux);
+
+ dev_dbg(&pdev->dev, "mux-mask\n");
+ tmp = info->mux_mask;
+ for (i = 0; i < info->nbanks; i++) {
+ for (j = 0; j < info->nmux; j++, tmp++) {
+ dev_dbg(&pdev->dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
+ }
+ }
+
+ dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+ dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+ info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func),
+ GFP_KERNEL);
+ if (!info->functions)
+ return -ENOMEM;
+
+ info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group),
+ GFP_KERNEL);
+ if (!info->groups)
+ return -ENOMEM;
+
+ dev_dbg(&pdev->dev, "nbanks = %d\n", info->nbanks);
+ dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
+ dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
+
+ i = 0;
+
+ for_each_child_of_node(np, child) {
+ if (of_device_is_compatible(child, gpio_compat))
+ continue;
+ ret = at91_pinctrl_parse_functions(child, info, i++);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to parse function\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int __devinit at91_pinctrl_probe(struct platform_device *pdev)
+{
+ struct at91_pinctrl *info;
+ struct pinctrl_pin_desc *pdesc;
+ int ret, i, j ,k;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ ret = at91_pinctrl_probe_dt(pdev, info);
+ if (ret)
+ return ret;
+
+ /*
+ * 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 < info->nbanks; i++) {
+ if (!gpio_chips[i]) {
+ dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
+ devm_kfree(&pdev->dev, info);
+ return -EPROBE_DEFER;
+ }
+ }
+
+ at91_pinctrl_desc.name = dev_name(&pdev->dev);
+ at91_pinctrl_desc.npins = info->nbanks * MAX_NB_GPIO_PER_BANK;
+ at91_pinctrl_desc.pins = pdesc =
+ devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL);
+
+ if (!at91_pinctrl_desc.pins)
+ return -ENOMEM;
+
+ for (i = 0 , k = 0; i < info->nbanks; i++) {
+ for (j = 0; j < MAX_NB_GPIO_PER_BANK; j++, k++) {
+ pdesc->number = k;
+ pdesc->name = kasprintf(GFP_KERNEL, "pio%c%d", i + 'A', j);
+ pdesc++;
+ }
+ }
+
+ platform_set_drvdata(pdev, info);
+ info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
+
+ if (!info->pctl) {
+ dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* We will handle a range of GPIO pins */
+ for (i = 0; i < info->nbanks; i++)
+ pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+
+ dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
+
+ return 0;
+
+err:
+ return ret;
+}
+
+static int __devexit at91_pinctrl_remove(struct platform_device *pdev)
+{
+ struct at91_pinctrl *info = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(info->pctl);
+
+ return 0;
+}
+
+static int at91_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;
+ int bank = chip->base / chip->ngpio;
+
+ dev_dbg(chip->dev, "%s:%d pio%c%d(%d)\n", __func__, __LINE__,
+ 'A' + bank, offset, gpio);
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void at91_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
+static int at91_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << offset;
+
+ writel_relaxed(mask, pio + PIO_ODR);
+ return 0;
+}
+
+static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << offset;
+ u32 pdsr;
+
+ pdsr = readl_relaxed(pio + PIO_PDSR);
+ return (pdsr & mask) != 0;
+}
+
+static void at91_gpio_set(struct gpio_chip *chip, unsigned offset,
+ int val)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << offset;
+
+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+}
+
+static int at91_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int val)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << offset;
+
+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
+ writel_relaxed(mask, pio + PIO_OER);
+
+ return 0;
+}
+
+static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ int virq;
+
+ if (offset < chip->ngpio)
+ virq = irq_create_mapping(at91_gpio->domain, offset);
+ else
+ virq = -ENXIO;
+
+ dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
+ chip->label, offset + chip->base, virq);
+ return virq;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ enum at91_mux mode;
+ int i;
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+ void __iomem *pio = at91_gpio->regbase;
+
+ for (i = 0; i < chip->ngpio; i++) {
+ unsigned pin = chip->base + i;
+ unsigned mask = pin_to_mask(pin);
+ const char *gpio_label;
+ u32 pdsr;
+
+ gpio_label = gpiochip_is_requested(chip, i);
+ if (!gpio_label)
+ continue;
+ mode = at91_gpio->ops->get_periph(pio, mask);
+ seq_printf(s, "[%s] GPIO%s%d: ",
+ gpio_label, chip->label, i);
+ if (mode == AT91_MUX_GPIO) {
+ pdsr = readl_relaxed(pio + PIO_PDSR);
+
+ seq_printf(s, "[gpio] %s\n",
+ pdsr & mask ?
+ "set" : "clear");
+ } else {
+ seq_printf(s, "[periph %c]\n",
+ mode + 'A' - 1);
+ }
+ }
+}
+#else
+#define at91_gpio_dbg_show NULL
+#endif
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler.
+ * First implementation always triggers on rising and falling edges
+ * whereas the newer PIO3 can be additionally configured to trigger on
+ * level, edge with any polarity.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << d->hwirq;
+
+ if (pio)
+ writel_relaxed(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << d->hwirq;
+
+ if (pio)
+ writel_relaxed(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+ switch (type) {
+ case IRQ_TYPE_NONE:
+ case IRQ_TYPE_EDGE_BOTH:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Alternate irq type for PIO3 support */
+static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned mask = 1 << d->hwirq;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ writel_relaxed(mask, pio + PIO_ESR);
+ writel_relaxed(mask, pio + PIO_REHLSR);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ writel_relaxed(mask, pio + PIO_ESR);
+ writel_relaxed(mask, pio + PIO_FELLSR);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ writel_relaxed(mask, pio + PIO_LSR);
+ writel_relaxed(mask, pio + PIO_FELLSR);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ writel_relaxed(mask, pio + PIO_LSR);
+ writel_relaxed(mask, pio + PIO_REHLSR);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ /*
+ * disable additional interrupt modes:
+ * fall back to default behavior
+ */
+ writel_relaxed(mask, pio + PIO_AIMDR);
+ return 0;
+ case IRQ_TYPE_NONE:
+ default:
+ pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
+ return -EINVAL;
+ }
+
+ /* enable additional interrupt modes */
+ writel_relaxed(mask, pio + PIO_AIMER);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
+{
+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
+ unsigned bank = at91_gpio->pioc_idx;
+
+ if (unlikely(bank >= MAX_GPIO_BANKS))
+ return -EINVAL;
+
+ irq_set_irq_wake(at91_gpio->pioc_virq, state);
+
+ return 0;
+}
+#else
+#define gpio_irq_set_wake NULL
+#endif
+
+static struct irq_chip gpio_irqchip = {
+ .name = "GPIO",
+ .irq_disable = gpio_irq_mask,
+ .irq_mask = gpio_irq_mask,
+ .irq_unmask = gpio_irq_unmask,
+ /* .irq_set_type is set dynamically */
+ .irq_set_wake = gpio_irq_set_wake,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irq_data *idata = irq_desc_get_irq_data(desc);
+ struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+ void __iomem *pio = at91_gpio->regbase;
+ unsigned long isr;
+ int n;
+
+ chained_irq_enter(chip, desc);
+ for (;;) {
+ /* Reading ISR acks pending (edge triggered) GPIO interrupts.
+ * When there none are pending, we're finished unless we need
+ * to process multiple banks (like ID_PIOCDE on sam9263).
+ */
+ isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR);
+ if (!isr) {
+ if (!at91_gpio->next)
+ break;
+ at91_gpio = at91_gpio->next;
+ pio = at91_gpio->regbase;
+ continue;
+ }
+
+ for_each_set_bit(n, &isr, BITS_PER_LONG) {
+ generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
+ }
+ }
+ chained_irq_exit(chip, desc);
+ /* now it may re-trigger */
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct at91_gpio_chip *at91_gpio = h->host_data;
+
+ irq_set_lockdep_class(virq, &gpio_lock_class);
+
+ /*
+ * Can use the "simple" and not "edge" handler since it's
+ * shorter, and the AIC handles interrupts sanely.
+ */
+ irq_set_chip_and_handler(virq, &gpio_irqchip,
+ handle_simple_irq);
+ set_irq_flags(virq, IRQF_VALID);
+ irq_set_chip_data(virq, at91_gpio);
+
+ return 0;
+}
+
+static int at91_gpio_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ struct at91_gpio_chip *at91_gpio = d->host_data;
+ int ret;
+ int pin = at91_gpio->chip.base + intspec[0];
+
+ if (WARN_ON(intsize < 2))
+ return -EINVAL;
+ *out_hwirq = intspec[0];
+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+ ret = gpio_request(pin, ctrlr->full_name);
+ if (ret)
+ return ret;
+
+ ret = gpio_direction_input(pin);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct irq_domain_ops at91_gpio_ops = {
+ .map = at91_gpio_irq_map,
+ .xlate = at91_gpio_irq_domain_xlate,
+};
+
+static int at91_gpio_of_irq_setup(struct device_node *node,
+ struct at91_gpio_chip *at91_gpio)
+{
+ struct at91_gpio_chip *prev = NULL;
+ struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
+
+ at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
+
+ /* Setup proper .irq_set_type function */
+ gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
+
+ /* Disable irqs of this PIO controller */
+ writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
+
+ /* Setup irq domain */
+ at91_gpio->domain = irq_domain_add_linear(node, at91_gpio->chip.ngpio,
+ &at91_gpio_ops, at91_gpio);
+ if (!at91_gpio->domain)
+ panic("at91_gpio.%d: couldn't allocate irq domain (DT).\n",
+ at91_gpio->pioc_idx);
+
+ /* Setup chained handler */
+ if (at91_gpio->pioc_idx)
+ prev = gpio_chips[at91_gpio->pioc_idx - 1];
+
+ /* The toplevel handler handles one bank of GPIOs, except
+ * on some SoC it can handles up to three...
+ * We only set up the handler for the first of the list.
+ */
+ if (prev && prev->next == at91_gpio)
+ return 0;
+
+ irq_set_chip_data(at91_gpio->pioc_virq, at91_gpio);
+ irq_set_chained_handler(at91_gpio->pioc_virq, gpio_irq_handler);
+
+ return 0;
+}
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip at91_gpio_template = {
+ .request = at91_gpio_request,
+ .free = at91_gpio_free,
+ .direction_input = at91_gpio_direction_input,
+ .get = at91_gpio_get,
+ .direction_output = at91_gpio_direction_output,
+ .set = at91_gpio_set,
+ .to_irq = at91_gpio_to_irq,
+ .dbg_show = at91_gpio_dbg_show,
+ .can_sleep = 0,
+ .ngpio = MAX_NB_GPIO_PER_BANK,
+};
+
+static void __devinit at91_gpio_probe_fixup(void)
+{
+ unsigned i;
+ struct at91_gpio_chip *at91_gpio, *last = NULL;
+
+ for (i = 0; i < gpio_banks; i++) {
+ at91_gpio = gpio_chips[i];
+
+ /*
+ * GPIO controller are grouped on some SoC:
+ * PIOC, PIOD and PIOE can share the same IRQ line
+ */
+ if (last && last->pioc_virq == at91_gpio->pioc_virq)
+ last->next = at91_gpio;
+ last = at91_gpio;
+ }
+}
+
+static struct of_device_id at91_gpio_of_match[] __devinitdata = {
+ { .compatible = "atmel,at91sam9x5-gpio", .data = &at91sam9x5_ops, },
+ { .compatible = "atmel,at91rm9200-gpio", .data = &at91rm9200_ops },
+ { /* sentinel */ }
+};
+
+static int __devinit at91_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+ struct at91_gpio_chip *at91_chip = NULL;
+ struct gpio_chip *chip;
+ struct pinctrl_gpio_range *range;
+ int ret = 0;
+ int irq, i;
+ int alias_idx = of_alias_get_id(np, "gpio");
+ uint32_t ngpio;
+ char **names;
+
+ BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips));
+ if (gpio_chips[alias_idx]) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENOENT;
+ goto err;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+ goto err;
+ }
+
+ at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL);
+ if (!at91_chip) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ at91_chip->regbase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!at91_chip->regbase) {
+ dev_err(&pdev->dev, "failed to map registers, ignoring.\n");
+ ret = -EBUSY;
+ goto err;
+ }
+
+ at91_chip->ops = (struct at91_pinctrl_mux_ops*)
+ of_match_device(at91_gpio_of_match, &pdev->dev)->data;
+ at91_chip->pioc_virq = irq;
+ at91_chip->pioc_idx = alias_idx;
+
+ at91_chip->clock = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(at91_chip->clock)) {
+ dev_err(&pdev->dev, "failed to get clock, ignoring.\n");
+ goto err;
+ }
+
+ if (clk_prepare(at91_chip->clock))
+ goto clk_prep_err;
+
+ /* enable PIO controller's clock */
+ if (clk_enable(at91_chip->clock)) {
+ dev_err(&pdev->dev, "failed to enable clock, ignoring.\n");
+ goto clk_err;
+ }
+
+ at91_chip->chip = at91_gpio_template;
+
+ chip = &at91_chip->chip;
+ chip->of_node = np;
+ chip->label = dev_name(&pdev->dev);
+ chip->dev = &pdev->dev;
+ chip->owner = THIS_MODULE;
+ chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;
+
+ if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
+ if (ngpio >= MAX_NB_GPIO_PER_BANK)
+ pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
+ alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
+ else
+ chip->ngpio = ngpio;
+ }
+
+ names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
+
+ if (!names) {
+ ret = -ENOMEM;
+ goto clk_err;
+ }
+
+ for (i = 0; i < chip->ngpio; i++)
+ names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
+
+ chip->names = (const char*const*)names;
+
+ range = &at91_chip->range;
+ range->name = chip->label;
+ range->id = alias_idx;
+ range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;
+
+ range->npins = chip->ngpio;
+ range->gc = chip;
+
+ ret = gpiochip_add(chip);
+ if (ret)
+ goto clk_err;
+
+ gpio_chips[alias_idx] = at91_chip;
+ gpio_banks = max(gpio_banks, alias_idx + 1);
+
+ at91_gpio_probe_fixup();
+
+ at91_gpio_of_irq_setup(np, at91_chip);
+
+ dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);
+
+ return 0;
+
+clk_err:
+ clk_unprepare(at91_chip->clock);
+clk_prep_err:
+ clk_put(at91_chip->clock);
+err:
+ dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);
+
+ return ret;
+}
+
+static struct platform_driver at91_gpio_driver = {
+ .driver = {
+ .name = "gpio-at91",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_gpio_of_match),
+ },
+ .probe = at91_gpio_probe,
+};
+
+static struct platform_driver at91_pinctrl_driver = {
+ .driver = {
+ .name = "pinctrl-at91",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91_pinctrl_of_match),
+ },
+ .probe = at91_pinctrl_probe,
+ .remove = __devexit_p(at91_pinctrl_remove),
+};
+
+static int __init at91_pinctrl_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&at91_gpio_driver);
+ if (ret)
+ return ret;
+ return platform_driver_register(&at91_pinctrl_driver);
+}
+arch_initcall(at91_pinctrl_init);
+
+static void __exit at91_pinctrl_exit(void)
+{
+ platform_driver_unregister(&at91_pinctrl_driver);
+}
+
+module_exit(at91_pinctrl_exit);
+MODULE_AUTHOR("Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>");
+MODULE_DESCRIPTION("Atmel AT91 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 7e9be18ec2d2..0b0e9b49a1b5 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -372,7 +372,7 @@ static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_linear_revmap(pc->irq_domain, offset);
}
-static struct gpio_chip bcm2835_gpio_chip __devinitconst = {
+static struct gpio_chip bcm2835_gpio_chip = {
.label = MODULE_NAME,
.owner = THIS_MODULE,
.request = bcm2835_gpio_request,
@@ -916,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
return 0;
}
-struct pinconf_ops bcm2835_pinconf_ops = {
+static struct pinconf_ops bcm2835_pinconf_ops = {
.pin_config_get = bcm2835_pinconf_get,
.pin_config_set = bcm2835_pinconf_set,
};
@@ -931,7 +931,7 @@ static struct pinctrl_desc bcm2835_pinctrl_desc = {
.owner = THIS_MODULE,
};
-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range __devinitconst = {
+static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
.name = MODULE_NAME,
.npins = BCM2835_NUM_GPIOS,
};
@@ -1042,7 +1042,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
+static int bcm2835_pinctrl_remove(struct platform_device *pdev)
{
struct bcm2835_pinctrl *pc = platform_get_drvdata(pdev);
@@ -1052,7 +1052,7 @@ static int __devexit bcm2835_pinctrl_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id bcm2835_pinctrl_match[] __devinitconst = {
+static struct of_device_id bcm2835_pinctrl_match[] = {
{ .compatible = "brcm,bcm2835-gpio" },
{}
};
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index b446c9641212..fbb37154471c 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/io.h>
+#include <linux/irqdomain.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@@ -64,10 +65,8 @@ struct u300_gpio {
struct gpio_chip chip;
struct list_head port_list;
struct clk *clk;
- struct resource *memres;
void __iomem *base;
struct device *dev;
- int irq_base;
u32 stride;
/* Register offsets */
u32 pcr;
@@ -83,6 +82,7 @@ struct u300_gpio_port {
struct list_head node;
struct u300_gpio *gpio;
char name[8];
+ struct irq_domain *domain;
int irq;
int number;
u8 toggle_edge_mode;
@@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct u300_gpio *gpio = to_u300_gpio(chip);
- int retirq = gpio->irq_base + offset;
+ int portno = offset >> 3;
+ struct u300_gpio_port *port = NULL;
+ struct list_head *p;
+ int retirq;
- dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
- retirq);
+ list_for_each(p, &gpio->port_list) {
+ port = list_entry(p, struct u300_gpio_port, node);
+ if (port->number == portno)
+ break;
+ }
+ if (port == NULL) {
+ dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
+ offset);
+ return -EINVAL;
+ }
+
+ /*
+ * The local hwirqs on the port are the lower three bits, there
+ * are exactly 8 IRQs per port since they are 8-bit
+ */
+ retirq = irq_find_mapping(port->domain, (offset & 0x7));
+
+ dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
+ offset, retirq, port->number);
return retirq;
}
@@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
- int offset = d->irq - gpio->irq_base;
+ int offset = (port->number << 3) + d->hwirq;
u32 val;
if ((trigger & IRQF_TRIGGER_RISING) &&
@@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
- int offset = d->irq - gpio->irq_base;
+ int offset = (port->number << 3) + d->hwirq;
u32 val;
unsigned long flags;
+ dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
+ d->hwirq, port->name, offset);
local_irq_save(flags);
val = readl(U300_PIN_REG(offset, ien));
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@@ -517,7 +539,7 @@ static void u300_gpio_irq_disable(struct irq_data *d)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
- int offset = d->irq - gpio->irq_base;
+ int offset = (port->number << 3) + d->hwirq;
u32 val;
unsigned long flags;
@@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
int irqoffset;
for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
- int pin_irq = gpio->irq_base + (port->number << 3)
- + irqoffset;
+ int pin_irq = irq_find_mapping(port->domain, irqoffset);
int offset = pinoffset + irqoffset;
dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
@@ -631,64 +652,86 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
list_for_each_safe(p, n, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node);
list_del(&port->node);
+ if (port->domain)
+ irq_domain_remove(port->domain);
kfree(port);
}
}
+/*
+ * Here we map a GPIO in the local gpio_chip pin space to a pin in
+ * the local pinctrl pin space. The pin controller used is
+ * pinctrl-u300.
+ */
+struct coh901_pinpair {
+ unsigned int offset;
+ unsigned int pin_base;
+};
+
+#define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b }
+
+static struct coh901_pinpair coh901_pintable[] = {
+ COH901_PINRANGE(10, 426),
+ COH901_PINRANGE(11, 180),
+ COH901_PINRANGE(12, 165), /* MS/MMC card insertion */
+ COH901_PINRANGE(13, 179),
+ COH901_PINRANGE(14, 178),
+ COH901_PINRANGE(16, 194),
+ COH901_PINRANGE(17, 193),
+ COH901_PINRANGE(18, 192),
+ COH901_PINRANGE(19, 191),
+ COH901_PINRANGE(20, 186),
+ COH901_PINRANGE(21, 185),
+ COH901_PINRANGE(22, 184),
+ COH901_PINRANGE(23, 183),
+ COH901_PINRANGE(24, 182),
+ COH901_PINRANGE(25, 181),
+};
+
static int __init u300_gpio_probe(struct platform_device *pdev)
{
struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
struct u300_gpio *gpio;
+ struct resource *memres;
int err = 0;
int portno;
u32 val;
u32 ifr;
int i;
- gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
- if (gpio == NULL) {
- dev_err(&pdev->dev, "failed to allocate memory\n");
+ gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
+ if (gpio == NULL)
return -ENOMEM;
- }
gpio->chip = u300_gpio_chip;
gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
- gpio->irq_base = plat->gpio_irq_base;
gpio->chip.dev = &pdev->dev;
gpio->chip.base = plat->gpio_base;
gpio->dev = &pdev->dev;
- /* Get GPIO clock */
- gpio->clk = clk_get(gpio->dev, NULL);
+ memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!memres) {
+ dev_err(gpio->dev, "could not get GPIO memory resource\n");
+ return -ENODEV;
+ }
+
+ gpio->base = devm_request_and_ioremap(&pdev->dev, memres);
+ if (!gpio->base) {
+ dev_err(gpio->dev, "could not get remap memory\n");
+ return -ENOMEM;
+ }
+
+ gpio->clk = devm_clk_get(gpio->dev, NULL);
if (IS_ERR(gpio->clk)) {
err = PTR_ERR(gpio->clk);
dev_err(gpio->dev, "could not get GPIO clock\n");
- goto err_no_clk;
+ return err;
}
+
err = clk_prepare_enable(gpio->clk);
if (err) {
dev_err(gpio->dev, "could not enable GPIO clock\n");
- goto err_no_clk_enable;
- }
-
- gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!gpio->memres) {
- dev_err(gpio->dev, "could not get GPIO memory resource\n");
- err = -ENODEV;
- goto err_no_resource;
- }
-
- if (!request_mem_region(gpio->memres->start,
- resource_size(gpio->memres),
- "GPIO Controller")) {
- err = -ENODEV;
- goto err_no_ioregion;
- }
-
- gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
- if (!gpio->base) {
- err = -ENOMEM;
- goto err_no_ioremap;
+ return err;
}
dev_info(gpio->dev,
@@ -732,18 +775,28 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
port->irq = platform_get_irq_byname(pdev,
port->name);
- dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
+ dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
port->name);
+ port->domain = irq_domain_add_linear(pdev->dev.of_node,
+ U300_GPIO_PINS_PER_PORT,
+ &irq_domain_simple_ops,
+ port);
+ if (!port->domain) {
+ err = -ENOMEM;
+ goto err_no_domain;
+ }
+
irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
/* For each GPIO pin set the unique IRQ handler */
for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
- int irqno = gpio->irq_base + (portno << 3) + i;
+ int irqno = irq_create_mapping(port->domain, i);
- dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
- irqno, port->name);
+ dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
+ gpio->chip.base + (port->number << 3) + i,
+ port->name, irqno);
irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
handle_simple_irq);
set_irq_flags(irqno, IRQF_VALID);
@@ -763,32 +816,31 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
goto err_no_chip;
}
- /* Spawn pin controller device as child of the GPIO, pass gpio chip */
- plat->pinctrl_device->dev.platform_data = &gpio->chip;
- err = platform_device_register(plat->pinctrl_device);
- if (err)
- goto err_no_pinctrl;
+ /*
+ * Add pinctrl pin ranges, the pin controller must be registered
+ * at this point
+ */
+ for (i = 0; i < ARRAY_SIZE(coh901_pintable); i++) {
+ struct coh901_pinpair *p = &coh901_pintable[i];
+
+ err = gpiochip_add_pin_range(&gpio->chip, "pinctrl-u300",
+ p->offset, p->pin_base, 1);
+ if (err)
+ goto err_no_range;
+ }
platform_set_drvdata(pdev, gpio);
return 0;
-err_no_pinctrl:
+err_no_range:
err = gpiochip_remove(&gpio->chip);
err_no_chip:
+err_no_domain:
err_no_port:
u300_gpio_free_ports(gpio);
- iounmap(gpio->base);
-err_no_ioremap:
- release_mem_region(gpio->memres->start, resource_size(gpio->memres));
-err_no_ioregion:
-err_no_resource:
clk_disable_unprepare(gpio->clk);
-err_no_clk_enable:
- clk_put(gpio->clk);
-err_no_clk:
- kfree(gpio);
- dev_info(&pdev->dev, "module ERROR:%d\n", err);
+ dev_err(&pdev->dev, "module ERROR:%d\n", err);
return err;
}
@@ -806,13 +858,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
return err;
}
u300_gpio_free_ports(gpio);
- iounmap(gpio->base);
- release_mem_region(gpio->memres->start,
- resource_size(gpio->memres));
clk_disable_unprepare(gpio->clk);
- clk_put(gpio->clk);
platform_set_drvdata(pdev, NULL);
- kfree(gpio);
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 21362f48d370..6ff665209a4c 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -36,6 +36,7 @@
/* list of external wakeup controllers supported */
static const struct of_device_id exynos_wkup_irq_ids[] = {
{ .compatible = "samsung,exynos4210-wakeup-eint", },
+ { }
};
static void exynos_gpio_irq_unmask(struct irq_data *irqd)
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index ee7305903470..8ed20e84cb02 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -322,7 +322,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
{
}
-struct pinconf_ops falcon_pinconf_ops = {
+static struct pinconf_ops falcon_pinconf_ops = {
.pin_config_get = falcon_pinconf_get,
.pin_config_set = falcon_pinconf_set,
.pin_config_group_get = falcon_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 63866d95357d..131d86d7c2a5 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -71,7 +71,7 @@ static const struct imx_pin_reg *imx_find_pin_reg(
break;
}
- if (!pin_reg) {
+ if (i == info->npin_regs) {
dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
info->pins[pin].name);
return NULL;
@@ -397,7 +397,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
}
}
-struct pinconf_ops imx_pinconf_ops = {
+static 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,
@@ -611,7 +611,7 @@ int __devinit imx_pinctrl_probe(struct platform_device *pdev,
return 0;
}
-int __devexit imx_pinctrl_remove(struct platform_device *pdev)
+int imx_pinctrl_remove(struct platform_device *pdev)
{
struct imx_pinctrl *ipctl = platform_get_drvdata(pdev);
diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c
index 3674d877ed7c..04364f7822b7 100644
--- a/drivers/pinctrl/pinctrl-imx23.c
+++ b/drivers/pinctrl/pinctrl-imx23.c
@@ -272,7 +272,7 @@ 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 = {
+static struct of_device_id imx23_pinctrl_of_match[] = {
{ .compatible = "fsl,imx23-pinctrl", },
{ /* sentinel */ }
};
@@ -285,7 +285,7 @@ static struct platform_driver imx23_pinctrl_driver = {
.of_match_table = imx23_pinctrl_of_match,
},
.probe = imx23_pinctrl_probe,
- .remove = __devexit_p(mxs_pinctrl_remove),
+ .remove = mxs_pinctrl_remove,
};
static int __init imx23_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c
index 0f5b2122b1ba..e1af2ba89004 100644
--- a/drivers/pinctrl/pinctrl-imx28.c
+++ b/drivers/pinctrl/pinctrl-imx28.c
@@ -388,7 +388,7 @@ 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 = {
+static struct of_device_id imx28_pinctrl_of_match[] = {
{ .compatible = "fsl,imx28-pinctrl", },
{ /* sentinel */ }
};
@@ -401,7 +401,7 @@ static struct platform_driver imx28_pinctrl_driver = {
.of_match_table = imx28_pinctrl_of_match,
},
.probe = imx28_pinctrl_probe,
- .remove = __devexit_p(mxs_pinctrl_remove),
+ .remove = mxs_pinctrl_remove,
};
static int __init imx28_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
index 82f109e26f27..1dbf5278acec 100644
--- a/drivers/pinctrl/pinctrl-imx35.c
+++ b/drivers/pinctrl/pinctrl-imx35.c
@@ -1559,7 +1559,7 @@ static struct imx_pinctrl_soc_info imx35_pinctrl_info = {
.npin_regs = ARRAY_SIZE(imx35_pin_regs),
};
-static struct of_device_id imx35_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx35_pinctrl_of_match[] = {
{ .compatible = "fsl,imx35-iomuxc", },
{ /* sentinel */ }
};
@@ -1576,7 +1576,7 @@ static struct platform_driver imx35_pinctrl_driver = {
.of_match_table = of_match_ptr(imx35_pinctrl_of_match),
},
.probe = imx35_pinctrl_probe,
- .remove = __devexit_p(imx_pinctrl_remove),
+ .remove = imx_pinctrl_remove,
};
static int __init imx35_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
index fb8468966779..131216558a7b 100644
--- a/drivers/pinctrl/pinctrl-imx51.c
+++ b/drivers/pinctrl/pinctrl-imx51.c
@@ -1286,7 +1286,7 @@ static struct imx_pinctrl_soc_info imx51_pinctrl_info = {
.npin_regs = ARRAY_SIZE(imx51_pin_regs),
};
-static struct of_device_id imx51_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx51_pinctrl_of_match[] = {
{ .compatible = "fsl,imx51-iomuxc", },
{ /* sentinel */ }
};
@@ -1303,7 +1303,7 @@ static struct platform_driver imx51_pinctrl_driver = {
.of_match_table = of_match_ptr(imx51_pinctrl_of_match),
},
.probe = imx51_pinctrl_probe,
- .remove = __devexit_p(imx_pinctrl_remove),
+ .remove = imx_pinctrl_remove,
};
static int __init imx51_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
index 783feb1ce064..ec4048691775 100644
--- a/drivers/pinctrl/pinctrl-imx53.c
+++ b/drivers/pinctrl/pinctrl-imx53.c
@@ -1613,7 +1613,7 @@ static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
.npin_regs = ARRAY_SIZE(imx53_pin_regs),
};
-static struct of_device_id imx53_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx53_pinctrl_of_match[] = {
{ .compatible = "fsl,imx53-iomuxc", },
{ /* sentinel */ }
};
@@ -1630,7 +1630,7 @@ static struct platform_driver imx53_pinctrl_driver = {
.of_match_table = of_match_ptr(imx53_pinctrl_of_match),
},
.probe = imx53_pinctrl_probe,
- .remove = __devexit_p(imx_pinctrl_remove),
+ .remove = imx_pinctrl_remove,
};
static int __init imx53_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
index e9bf71fbedca..844ab13c93a3 100644
--- a/drivers/pinctrl/pinctrl-imx6q.c
+++ b/drivers/pinctrl/pinctrl-imx6q.c
@@ -2297,7 +2297,7 @@ static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
.npin_regs = ARRAY_SIZE(imx6q_pin_regs),
};
-static struct of_device_id imx6q_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id imx6q_pinctrl_of_match[] = {
{ .compatible = "fsl,imx6q-iomuxc", },
{ /* sentinel */ }
};
@@ -2314,7 +2314,7 @@ static struct platform_driver imx6q_pinctrl_driver = {
.of_match_table = of_match_ptr(imx6q_pinctrl_of_match),
},
.probe = imx6q_pinctrl_probe,
- .remove = __devexit_p(imx_pinctrl_remove),
+ .remove = imx_pinctrl_remove,
};
static int __init imx6q_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index 07ba7682cf22..15f501d89026 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -46,8 +46,8 @@ static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
return 0;
}
-void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map *map, unsigned num_maps)
+static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
{
int i;
@@ -128,10 +128,10 @@ static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
return ret;
}
-int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
- struct device_node *np_config,
- struct pinctrl_map **map,
- unsigned *num_maps)
+static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np_config,
+ struct pinctrl_map **map,
+ unsigned *num_maps)
{
struct pinctrl_map *tmp;
struct device_node *np;
@@ -275,16 +275,6 @@ static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
return 0;
}
-static void ltq_pmx_disable(struct pinctrl_dev *pctrldev,
- unsigned func,
- unsigned group)
-{
- /*
- * Nothing to do here. However, pinconf_check_ops() requires this
- * callback to be defined.
- */
-}
-
static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -312,7 +302,6 @@ static struct pinmux_ops ltq_pmx_ops = {
.get_function_name = ltq_pmx_func_name,
.get_function_groups = ltq_pmx_get_groups,
.enable = ltq_pmx_enable,
- .disable = ltq_pmx_disable,
.gpio_request_enable = ltq_pmx_gpio_request_enable,
};
diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
index 2cfed552bbe4..4fbb3db3f1c1 100644
--- a/drivers/pinctrl/pinctrl-mmp2.c
+++ b/drivers/pinctrl/pinctrl-mmp2.c
@@ -691,7 +691,7 @@ static int __devinit mmp2_pinmux_probe(struct platform_device *pdev)
return pxa3xx_pinctrl_register(pdev, &mmp2_info);
}
-static int __devexit mmp2_pinmux_remove(struct platform_device *pdev)
+static int mmp2_pinmux_remove(struct platform_device *pdev)
{
return pxa3xx_pinctrl_unregister(pdev);
}
@@ -702,7 +702,7 @@ static struct platform_driver mmp2_pinmux_driver = {
.owner = THIS_MODULE,
},
.probe = mmp2_pinmux_probe,
- .remove = __devexit_p(mmp2_pinmux_remove),
+ .remove = mmp2_pinmux_remove,
};
static int __init mmp2_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index 4ba4636b6a4a..180f16379ec1 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, "0x%lx", config);
}
-struct pinconf_ops mxs_pinconf_ops = {
+static 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,
@@ -522,7 +522,7 @@ err:
}
EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
-int __devexit mxs_pinctrl_remove(struct platform_device *pdev)
+int mxs_pinctrl_remove(struct platform_device *pdev)
{
struct mxs_pinctrl_data *d = platform_get_drvdata(pdev);
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c
index debaa75b0552..7d88ae352119 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c
@@ -475,8 +475,10 @@ static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
DB8500_PIN_AG9, DB8500_PIN_AG8 };
-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 clkout1_a_1_pins[] = { DB8500_PIN_AH7 };
+static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 };
+static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { 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,
@@ -592,7 +594,8 @@ 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 clkout1_c_1_pins[] = { DB8500_PIN_AH13 };
+static const unsigned clkout2_c_1_pins[] = { 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 };
@@ -600,14 +603,66 @@ 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 u2rx_oc1_1_pins[] = { DB8500_PIN_AB2 };
+static const unsigned stmape_oc1_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_Y4,
+ DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned remap0_oc1_1_pins[] = { DB8500_PIN_E1 };
+static const unsigned remap1_oc1_1_pins[] = { DB8500_PIN_E2 };
+static const unsigned ptma9_oc1_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 };
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 rf_oc1_1_pins[] = { DB8500_PIN_D8, DB8500_PIN_D9 };
+static const unsigned hxclk_oc1_1_pins[] = { DB8500_PIN_D16 };
+static const unsigned uartmodrx_oc1_1_pins[] = { DB8500_PIN_B17 };
+static const unsigned uartmodtx_oc1_1_pins[] = { DB8500_PIN_C16 };
+static const unsigned stmmod_oc1_1_pins[] = { DB8500_PIN_C19, DB8500_PIN_C17,
+ DB8500_PIN_A18, DB8500_PIN_C18, DB8500_PIN_B19 };
+static const unsigned hxgpio_oc1_1_pins[] = { 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 rf_oc1_2_pins[] = { DB8500_PIN_C23, DB8500_PIN_D23 };
static const unsigned spi2_oc1_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
DB8500_PIN_AH12, DB8500_PIN_AH11 };
static const unsigned spi2_oc1_2_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12,
DB8500_PIN_AH11 };
+/* Other C2 column */
+static const unsigned sbag_oc2_1_pins[] = { DB8500_PIN_AA4, DB8500_PIN_AB2,
+ DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
+static const unsigned etmr4_oc2_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 };
+static const unsigned ptma9_oc2_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 };
+
+/* Other C3 column */
+static const unsigned stmmod_oc3_1_pins[] = { DB8500_PIN_AB2, DB8500_PIN_W2,
+ DB8500_PIN_W3, DB8500_PIN_V3, DB8500_PIN_V2 };
+static const unsigned stmmod_oc3_2_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+ DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3 };
+static const unsigned uartmodrx_oc3_1_pins[] = { DB8500_PIN_H2 };
+static const unsigned uartmodtx_oc3_1_pins[] = { DB8500_PIN_J2 };
+static const unsigned etmr4_oc3_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 };
+
+/* Other C4 column */
+static const unsigned sbag_oc4_1_pins[] = { DB8500_PIN_G5, DB8500_PIN_G4,
+ DB8500_PIN_H4, DB8500_PIN_H3, DB8500_PIN_J3, DB8500_PIN_H1 };
+static const unsigned hwobs_oc4_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 };
+
#define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
@@ -639,6 +694,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
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(kp_a_2, 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),
@@ -647,8 +703,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
DB8500_PIN_GROUP(hsit_a_2, 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(clkout1_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+ DB8500_PIN_GROUP(clkout2_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),
@@ -720,15 +778,41 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
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(clkout1_c_1, NMK_GPIO_ALT_C),
+ DB8500_PIN_GROUP(clkout2_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 */
+ DB8500_PIN_GROUP(u2rx_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(stmape_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(remap0_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(remap1_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(ptma9_oc1_1, NMK_GPIO_ALT_C1),
DB8500_PIN_GROUP(kp_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(rf_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(hxclk_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(uartmodrx_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(uartmodtx_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(stmmod_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(hxgpio_oc1_1, NMK_GPIO_ALT_C1),
+ DB8500_PIN_GROUP(rf_oc1_2, NMK_GPIO_ALT_C1),
DB8500_PIN_GROUP(spi2_oc1_1, NMK_GPIO_ALT_C1),
DB8500_PIN_GROUP(spi2_oc1_2, NMK_GPIO_ALT_C1),
+ /* Other alt C2 column */
+ DB8500_PIN_GROUP(sbag_oc2_1, NMK_GPIO_ALT_C2),
+ DB8500_PIN_GROUP(etmr4_oc2_1, NMK_GPIO_ALT_C2),
+ DB8500_PIN_GROUP(ptma9_oc2_1, NMK_GPIO_ALT_C2),
+ /* Other alt C3 column */
+ DB8500_PIN_GROUP(stmmod_oc3_1, NMK_GPIO_ALT_C3),
+ DB8500_PIN_GROUP(stmmod_oc3_2, NMK_GPIO_ALT_C3),
+ DB8500_PIN_GROUP(uartmodrx_oc3_1, NMK_GPIO_ALT_C3),
+ DB8500_PIN_GROUP(uartmodtx_oc3_1, NMK_GPIO_ALT_C3),
+ DB8500_PIN_GROUP(etmr4_oc3_1, NMK_GPIO_ALT_C3),
+ /* Other alt C4 column */
+ DB8500_PIN_GROUP(sbag_oc4_1, NMK_GPIO_ALT_C4),
+ DB8500_PIN_GROUP(hwobs_oc4_1, NMK_GPIO_ALT_C4),
};
/* We use this macro to define the groups applicable to a function */
@@ -742,7 +826,7 @@ DB8500_FUNC_GROUPS(u1, "u1rxtx_a_1", "u1ctsrts_a_1");
* 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");
+ "u2rxtx_c_2", "u2rxtx_c_3", "u2rx_oc1_1");
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
@@ -757,7 +841,7 @@ 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_b_2", "kp_c_1", "kp_oc1_1");
+DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "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");
@@ -773,7 +857,8 @@ 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", "mc1_a_2", "mc1dir_a_1");
DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
-DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1");
+DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1",
+ "clkout2_a_1", "clkout2_a_2", "clkout2_c_1");
DB8500_FUNC_GROUPS(usb, "usb_a_1");
DB8500_FUNC_GROUPS(trig, "trig_b_1");
DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
@@ -784,8 +869,10 @@ DB8500_FUNC_GROUPS(i2c2, "i2c2_b_1", "i2c2_b_2");
* 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");
+ "uartmodrx_c_1", "uartmod_tx_c_1", "uartmodrx_oc1_1",
+ "uartmodtx_oc1_1", "uartmodrx_oc3_1", "uartmodtx_oc3_1");
+DB8500_FUNC_GROUPS(stmmod, "stmmod_b_1", "stmmod_c_1", "stmmod_oc1_1",
+ "stmmod_oc3_1", "stmmod_oc3_2");
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", "smcs1_b_1", "smcleale_c_1",
@@ -799,13 +886,19 @@ 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(stmape, "stmape_c_1", "stmape_c_2", "stmape_oc1_1");
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", "spi2_oc1_2");
-
+DB8500_FUNC_GROUPS(remap, "remap0_oc1_1", "remap1_oc1_1");
+DB8500_FUNC_GROUPS(sbag, "sbag_oc2_1", "sbag_oc4_1");
+DB8500_FUNC_GROUPS(ptm, "ptma9_oc1_1", "ptma9_oc2_1");
+DB8500_FUNC_GROUPS(rf, "rf_oc1_1", "rf_oc1_2");
+DB8500_FUNC_GROUPS(hx, "hxclk_oc1_1", "hxgpio_oc1_1");
+DB8500_FUNC_GROUPS(etm, "etmr4_oc2_1", "etmr4_oc3_1");
+DB8500_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
#define FUNCTION(fname) \
{ \
.name = #fname, \
@@ -858,6 +951,12 @@ static const struct nmk_function nmk_db8500_functions[] = {
FUNCTION(i2c3),
FUNCTION(spi0),
FUNCTION(spi2),
+ FUNCTION(remap),
+ FUNCTION(ptm),
+ FUNCTION(rf),
+ FUNCTION(hx),
+ FUNCTION(etm),
+ FUNCTION(hwobs),
};
static const struct prcm_gpiocr_altcx_pin_desc db8500_altcx_pins[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8540.c b/drivers/pinctrl/pinctrl-nomadik-db8540.c
index 52fc30181f7e..bb6a4016322a 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8540.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8540.c
@@ -460,8 +460,10 @@ static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 };
static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
DB8540_PIN_E10, DB8540_PIN_B12 };
-static const unsigned clkout_a_1_pins[] = { DB8540_PIN_D11, DB8540_PIN_AJ6 };
-static const unsigned clkout_a_2_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 };
+static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 };
+static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 };
+static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 };
static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 };
static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15,
DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16,
@@ -698,8 +700,10 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
- DB8540_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
- DB8540_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+ DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+ DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+ DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+ DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
/* Altfunction B column */
@@ -822,6 +826,7 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
+ DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4),
};
@@ -830,7 +835,8 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
static const char * const a##_groups[] = { b };
DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1");
-DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout_a_1", "clkout_a_2");
+DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2",
+ "clkout2_a_1", "clkout2_a_2");
DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index cf82d9ce4dee..8ef3e85cb011 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -30,26 +30,10 @@
#include <linux/pinctrl/pinconf.h>
/* Since we request GPIOs from ourself */
#include <linux/pinctrl/consumer.h>
-/*
- * For the U8500 archs, use the PRCMU register interface, for the older
- * Nomadik, provide some stubs. The functions using these will only be
- * called on the U8500 series.
- */
-#ifdef CONFIG_ARCH_U8500
-#include <linux/mfd/dbx500-prcmu.h>
-#else
-static inline u32 prcmu_read(unsigned int reg) {
- return 0;
-}
-static inline void prcmu_write(unsigned int reg, u32 value) {}
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
-#endif
+#include <linux/platform_data/pinctrl-nomadik.h>
#include <asm/mach/irq.h>
-#include <plat/pincfg.h>
-#include <plat/gpio-nomadik.h>
-
#include "pinctrl-nomadik.h"
/*
@@ -60,8 +44,6 @@ static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
* Symbols in this file are called "nmk_gpio" for "nomadik gpio"
*/
-#define NMK_GPIO_PER_CHIP 32
-
struct nmk_gpio_chip {
struct gpio_chip chip;
struct irq_domain *domain;
@@ -86,10 +68,18 @@ struct nmk_gpio_chip {
u32 lowemi;
};
+/**
+ * struct nmk_pinctrl - state container for the Nomadik pin controller
+ * @dev: containing device pointer
+ * @pctl: corresponding pin controller device
+ * @soc: SoC data for this specific chip
+ * @prcm_base: PRCM register range virtual base
+ */
struct nmk_pinctrl {
struct device *dev;
struct pinctrl_dev *pctl;
const struct nmk_pinctrl_soc_data *soc;
+ void __iomem *prcm_base;
};
static struct nmk_gpio_chip *
@@ -251,6 +241,15 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
}
+static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
+{
+ u32 val;
+
+ val = readl(reg);
+ val = ((val & ~mask) | (value & mask));
+ writel(val, reg);
+}
+
static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
unsigned offset, unsigned alt_num)
{
@@ -289,8 +288,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
if (pin_desc->altcx[i].used == true) {
reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
bit = pin_desc->altcx[i].control_bit;
- if (prcmu_read(reg) & BIT(bit)) {
- prcmu_write_masked(reg, BIT(bit), 0);
+ if (readl(npct->prcm_base + reg) & BIT(bit)) {
+ nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
dev_dbg(npct->dev,
"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
offset, i+1);
@@ -318,8 +317,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
if (pin_desc->altcx[i].used == true) {
reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
bit = pin_desc->altcx[i].control_bit;
- if (prcmu_read(reg) & BIT(bit)) {
- prcmu_write_masked(reg, BIT(bit), 0);
+ if (readl(npct->prcm_base + reg) & BIT(bit)) {
+ nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
dev_dbg(npct->dev,
"PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
offset, i+1);
@@ -331,7 +330,7 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
bit = pin_desc->altcx[alt_index].control_bit;
dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
offset, alt_index+1);
- prcmu_write_masked(reg, BIT(bit), BIT(bit));
+ nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
}
static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
@@ -536,7 +535,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
* and its sleep mode based on the specified configuration. The @cfg is
* usually one of the SoC specific macros defined in mach/<soc>-pins.h. These
* are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
+ * <linux/platform_data/pinctrl-nomadik.h>
*
* If a pin's mode is set to GPIO, it is configured as an input to avoid
* side-effects. The gpio can be manipulated later using standard GPIO API
@@ -675,6 +674,35 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode)
}
EXPORT_SYMBOL(nmk_gpio_set_mode);
+static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
+{
+ int i;
+ u16 reg;
+ u8 bit;
+ struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
+ const struct prcm_gpiocr_altcx_pin_desc *pin_desc;
+ const u16 *gpiocr_regs;
+
+ for (i = 0; i < npct->soc->npins_altcx; i++) {
+ if (npct->soc->altcx_pins[i].pin == gpio)
+ break;
+ }
+ if (i == npct->soc->npins_altcx)
+ return NMK_GPIO_ALT_C;
+
+ pin_desc = npct->soc->altcx_pins + i;
+ gpiocr_regs = npct->soc->prcm_gpiocr_registers;
+ for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) {
+ if (pin_desc->altcx[i].used == true) {
+ reg = gpiocr_regs[pin_desc->altcx[i].reg_index];
+ bit = pin_desc->altcx[i].control_bit;
+ if (readl(npct->prcm_base + reg) & BIT(bit))
+ return NMK_GPIO_ALT_C+i+1;
+ }
+ }
+ return NMK_GPIO_ALT_C;
+}
+
int nmk_gpio_get_mode(int gpio)
{
struct nmk_gpio_chip *nmk_chip;
@@ -1063,8 +1091,9 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
#include <linux/seq_file.h>
-static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
- unsigned offset, unsigned gpio)
+static void nmk_gpio_dbg_show_one(struct seq_file *s,
+ struct pinctrl_dev *pctldev, struct gpio_chip *chip,
+ unsigned offset, unsigned gpio)
{
const char *label = gpiochip_is_requested(chip, offset);
struct nmk_gpio_chip *nmk_chip =
@@ -1078,12 +1107,18 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip,
[NMK_GPIO_ALT_A] = "altA",
[NMK_GPIO_ALT_B] = "altB",
[NMK_GPIO_ALT_C] = "altC",
+ [NMK_GPIO_ALT_C+1] = "altC1",
+ [NMK_GPIO_ALT_C+2] = "altC2",
+ [NMK_GPIO_ALT_C+3] = "altC3",
+ [NMK_GPIO_ALT_C+4] = "altC4",
};
clk_enable(nmk_chip->clk);
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);
+ if ((mode == NMK_GPIO_ALT_C) && pctldev)
+ mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio);
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
gpio, label ?: "(none)",
@@ -1127,13 +1162,14 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
unsigned gpio = chip->base;
for (i = 0; i < chip->ngpio; i++, gpio++) {
- nmk_gpio_dbg_show_one(s, chip, i, gpio);
+ nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio);
seq_printf(s, "\n");
}
}
#else
static inline void nmk_gpio_dbg_show_one(struct seq_file *s,
+ struct pinctrl_dev *pctldev,
struct gpio_chip *chip,
unsigned offset, unsigned gpio)
{
@@ -1250,8 +1286,8 @@ 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)
+static 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;
@@ -1464,7 +1500,7 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
return;
}
chip = range->gc;
- nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset);
+ nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset);
}
static struct pinctrl_ops nmk_pinctrl_ops = {
@@ -1635,9 +1671,9 @@ static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
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)
+static 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;
@@ -1666,9 +1702,9 @@ int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
return 0;
}
-void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned offset)
+static 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);
@@ -1686,17 +1722,15 @@ static struct pinmux_ops nmk_pinmux_ops = {
.gpio_disable_free = nmk_gpio_disable_free,
};
-int nmk_pin_config_get(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *config)
+static 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 int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long config)
{
static const char *pullnames[] = {
[NMK_GPIO_PULL_NONE] = "none",
@@ -1818,6 +1852,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
const struct platform_device_id *platid = platform_get_device_id(pdev);
struct device_node *np = pdev->dev.of_node;
struct nmk_pinctrl *npct;
+ struct resource *res;
unsigned int version = 0;
int i;
@@ -1827,9 +1862,14 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
if (platid)
version = platid->driver_data;
- else if (np)
- version = (unsigned int)
- of_match_device(nmk_pinctrl_match, &pdev->dev)->data;
+ else if (np) {
+ const struct of_device_id *match;
+
+ match = of_match_device(nmk_pinctrl_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
+ version = (unsigned int) match->data;
+ }
/* Poke in other ASIC variants here */
if (version == PINCTRL_NMK_STN8815)
@@ -1839,22 +1879,37 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
if (version == PINCTRL_NMK_DB8540)
nmk_pinctrl_db8540_init(&npct->soc);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res) {
+ npct->prcm_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!npct->prcm_base) {
+ dev_err(&pdev->dev,
+ "failed to ioremap PRCM registers\n");
+ return -ENOMEM;
+ }
+ } else {
+ dev_info(&pdev->dev,
+ "No PRCM base, assume no ALT-Cx control is available\n");
+ }
+
/*
* 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]) {
+ if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) {
dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i);
return -EPROBE_DEFER;
}
- npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip;
+ npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->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");
@@ -1889,6 +1944,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = {
{ "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
{ "pinctrl-db8500", PINCTRL_NMK_DB8500 },
{ "pinctrl-db8540", PINCTRL_NMK_DB8540 },
+ { }
};
static struct platform_driver nmk_pinctrl_driver = {
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h
index eef316e979a0..bcd4191e10ea 100644
--- a/drivers/pinctrl/pinctrl-nomadik.h
+++ b/drivers/pinctrl/pinctrl-nomadik.h
@@ -1,7 +1,7 @@
#ifndef PINCTRL_PINCTRL_NOMADIK_H
#define PINCTRL_PINCTRL_NOMADIK_H
-#include <plat/gpio-nomadik.h>
+#include <linux/platform_data/pinctrl-nomadik.h>
/* Package definitions */
#define PINCTRL_NMK_STN8815 0
diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
index c1997fa7f28c..cb771e4a6355 100644
--- a/drivers/pinctrl/pinctrl-pxa168.c
+++ b/drivers/pinctrl/pinctrl-pxa168.c
@@ -620,7 +620,7 @@ static int __devinit pxa168_pinmux_probe(struct platform_device *pdev)
return pxa3xx_pinctrl_register(pdev, &pxa168_info);
}
-static int __devexit pxa168_pinmux_remove(struct platform_device *pdev)
+static int pxa168_pinmux_remove(struct platform_device *pdev)
{
return pxa3xx_pinctrl_unregister(pdev);
}
@@ -631,7 +631,7 @@ static struct platform_driver pxa168_pinmux_driver = {
.owner = THIS_MODULE,
},
.probe = pxa168_pinmux_probe,
- .remove = __devexit_p(pxa168_pinmux_remove),
+ .remove = pxa168_pinmux_remove,
};
static int __init pxa168_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
index f14cd6ba4c0b..51f8a388b917 100644
--- a/drivers/pinctrl/pinctrl-pxa3xx.c
+++ b/drivers/pinctrl/pinctrl-pxa3xx.c
@@ -173,7 +173,6 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
{
struct pinctrl_desc *desc;
struct resource *res;
- int ret = 0;
if (!info || !info->cputype)
return -EINVAL;
@@ -188,23 +187,17 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
- info->phy_base = res->start;
- info->phy_size = resource_size(res);
- info->virt_base = ioremap(info->phy_base, info->phy_size);
+ info->virt_base = devm_request_and_ioremap(&pdev->dev, res);
if (!info->virt_base)
return -ENOMEM;
info->pctrl = pinctrl_register(desc, &pdev->dev, info);
if (!info->pctrl) {
dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
platform_set_drvdata(pdev, info);
return 0;
-err:
- iounmap(info->virt_base);
- return ret;
}
int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
@@ -212,7 +205,6 @@ int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
pinctrl_unregister(info->pctrl);
- iounmap(info->virt_base);
platform_set_drvdata(pdev, NULL);
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.h b/drivers/pinctrl/pinctrl-pxa3xx.h
index 8135744d6599..92fad0880834 100644
--- a/drivers/pinctrl/pinctrl-pxa3xx.h
+++ b/drivers/pinctrl/pinctrl-pxa3xx.h
@@ -60,8 +60,6 @@ struct pxa3xx_pinmux_info {
struct device *dev;
struct pinctrl_dev *pctrl;
enum pxa_cpu_type cputype;
- unsigned int phy_base;
- unsigned int phy_size;
void __iomem *virt_base;
struct pxa3xx_mfp_pin *mfp;
diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
index c72ab4b9cc8c..5fecd221b830 100644
--- a/drivers/pinctrl/pinctrl-pxa910.c
+++ b/drivers/pinctrl/pinctrl-pxa910.c
@@ -976,7 +976,7 @@ static int __devinit pxa910_pinmux_probe(struct platform_device *pdev)
return pxa3xx_pinctrl_register(pdev, &pxa910_info);
}
-static int __devexit pxa910_pinmux_remove(struct platform_device *pdev)
+static int pxa910_pinmux_remove(struct platform_device *pdev)
{
return pxa3xx_pinctrl_unregister(pdev);
}
@@ -987,7 +987,7 @@ static struct platform_driver pxa910_pinmux_driver = {
.owner = THIS_MODULE,
},
.probe = pxa910_pinmux_probe,
- .remove = __devexit_p(pxa910_pinmux_remove),
+ .remove = pxa910_pinmux_remove,
};
static int __init pxa910_pinmux_init(void)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 726a729a2ec9..79642831bba2 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -30,6 +30,7 @@
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
#define PCS_OFF_DISABLED ~0U
+#define PCS_MAX_GPIO_VALUES 2
/**
* struct pcs_pingroup - pingroups for a function
@@ -77,6 +78,16 @@ struct pcs_function {
};
/**
+ * struct pcs_gpio_range - pinctrl gpio range
+ * @range: subrange of the GPIO number space
+ * @gpio_func: gpio function value in the pinmux register
+ */
+struct pcs_gpio_range {
+ struct pinctrl_gpio_range range;
+ int gpio_func;
+};
+
+/**
* struct pcs_data - wrapper for data needed by pinctrl framework
* @pa: pindesc array
* @cur: index to current element
@@ -244,15 +255,15 @@ static int pcs_get_group_pins(struct pinctrl_dev *pctldev,
static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s,
- unsigned offset)
+ unsigned pin)
{
struct pcs_device *pcs;
- unsigned val;
+ unsigned val, mux_bytes;
pcs = pinctrl_dev_get_drvdata(pctldev);
- val = pcs->read(pcs->base + offset);
- val &= pcs->fmask;
+ mux_bytes = pcs->width / BITS_PER_BYTE;
+ val = pcs->read(pcs->base + pin * mux_bytes);
seq_printf(s, "%08x %s " , val, DRIVER_NAME);
}
@@ -403,9 +414,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
}
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range, unsigned offset)
+ struct pinctrl_gpio_range *range, unsigned pin)
{
- return -ENOTSUPP;
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_gpio_range *gpio = NULL;
+ int end, mux_bytes;
+ unsigned data;
+
+ gpio = container_of(range, struct pcs_gpio_range, range);
+ end = range->pin_base + range->npins - 1;
+ if (pin < range->pin_base || pin > end) {
+ dev_err(pctldev->dev,
+ "pin %d isn't in the range of %d to %d\n",
+ pin, range->pin_base, end);
+ return -EINVAL;
+ }
+ mux_bytes = pcs->width / BITS_PER_BYTE;
+ data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+ data |= gpio->gpio_func;
+ pcs->write(data, pcs->base + pin * mux_bytes);
+ return 0;
}
static struct pinmux_ops pcs_pinmux_ops = {
@@ -772,7 +800,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
pcs = pinctrl_dev_get_drvdata(pctldev);
*map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
- if (!map)
+ if (!*map)
return -ENOMEM;
*num_maps = 0;
@@ -879,6 +907,50 @@ static void pcs_free_resources(struct pcs_device *pcs)
static struct of_device_id pcs_of_match[];
+static int __devinit pcs_add_gpio_range(struct device_node *node,
+ struct pcs_device *pcs)
+{
+ struct pcs_gpio_range *gpio;
+ struct device_node *child;
+ struct resource r;
+ const char name[] = "pinctrl-single";
+ u32 gpiores[PCS_MAX_GPIO_VALUES];
+ int ret, i = 0, mux_bytes = 0;
+
+ for_each_child_of_node(node, child) {
+ ret = of_address_to_resource(child, 0, &r);
+ if (ret < 0)
+ continue;
+ memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES);
+ ret = of_property_read_u32_array(child, "pinctrl-single,gpio",
+ gpiores, PCS_MAX_GPIO_VALUES);
+ if (ret < 0)
+ continue;
+ gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL);
+ if (!gpio) {
+ dev_err(pcs->dev, "failed to allocate pcs gpio\n");
+ return -ENOMEM;
+ }
+ gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name),
+ GFP_KERNEL);
+ if (!gpio->range.name) {
+ dev_err(pcs->dev, "failed to allocate range name\n");
+ return -ENOMEM;
+ }
+ memcpy((char *)gpio->range.name, name, sizeof(name));
+
+ gpio->range.id = i++;
+ gpio->range.base = gpiores[0];
+ gpio->gpio_func = gpiores[1];
+ mux_bytes = pcs->width / BITS_PER_BYTE;
+ gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes;
+ gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
+
+ pinctrl_add_gpio_range(pcs->pctl, &gpio->range);
+ }
+ return 0;
+}
+
static int __devinit pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -975,6 +1047,10 @@ static int __devinit pcs_probe(struct platform_device *pdev)
goto free;
}
+ ret = pcs_add_gpio_range(np, pcs);
+ if (ret < 0)
+ goto free;
+
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
pcs->desc.npins, pcs->base, pcs->size);
@@ -986,7 +1062,7 @@ free:
return ret;
}
-static int __devexit pcs_remove(struct platform_device *pdev)
+static int pcs_remove(struct platform_device *pdev)
{
struct pcs_device *pcs = platform_get_drvdata(pdev);
@@ -998,7 +1074,7 @@ static int __devexit pcs_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id pcs_of_match[] __devinitdata = {
+static struct of_device_id pcs_of_match[] = {
{ .compatible = DRIVER_NAME, },
{ },
};
@@ -1006,7 +1082,7 @@ MODULE_DEVICE_TABLE(of, pcs_of_match);
static struct platform_driver pcs_driver = {
.probe = pcs_probe,
- .remove = __devexit_p(pcs_remove),
+ .remove = pcs_remove,
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index 9ecacf3d0a75..a4f0c5e487d5 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -32,10 +32,10 @@
#define SIRFSOC_NUM_PADS 622
#define SIRFSOC_RSC_PIN_MUX 0x4
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
@@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank {
int id;
int parent_irq;
spinlock_t lock;
+ bool is_marco; /* for marco, some registers are different with prima2 */
};
static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
@@ -191,6 +192,7 @@ struct sirfsoc_pmx {
struct pinctrl_dev *pmx;
void __iomem *gpio_virtbase;
void __iomem *rsc_virtbase;
+ bool is_marco;
};
/* SIRFSOC_GPIO_PAD_EN set */
@@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector
for (i = 0; i < mux->muxmask_counts; i++) {
u32 muxval;
- muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
- if (enable)
- muxval = muxval & ~mask[i].mask;
- else
- muxval = muxval | mask[i].mask;
- writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ if (!spmx->is_marco) {
+ muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ if (enable)
+ muxval = muxval & ~mask[i].mask;
+ else
+ muxval = muxval | mask[i].mask;
+ writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ } else {
+ if (enable)
+ writel(mask[i].mask, spmx->gpio_virtbase +
+ SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
+ else
+ writel(mask[i].mask, spmx->gpio_virtbase +
+ SIRFSOC_GPIO_PAD_EN(mask[i].group));
+ }
}
if (mux->funcmask && enable) {
@@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
spmx = pinctrl_dev_get_drvdata(pmxdev);
- muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
- muxval = muxval | (1 << (offset - range->pin_base));
- writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+ if (!spmx->is_marco) {
+ muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+ muxval = muxval | (1 << (offset - range->pin_base));
+ writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+ } else {
+ writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
+ SIRFSOC_GPIO_PAD_EN(group));
+ }
return 0;
}
@@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
{
const struct of_device_id rsc_ids[] = {
{ .compatible = "sirf,prima2-rsc" },
+ { .compatible = "sirf,marco-rsc" },
{}
};
struct device_node *np;
@@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
goto out_no_rsc_remap;
}
+ if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+ spmx->is_marco = 1;
+
/* Now register the pin controller and all pins it handles */
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
if (!spmx->pmx) {
@@ -1285,8 +1305,9 @@ out_no_gpio_remap:
return ret;
}
-static const struct of_device_id pinmux_ids[] __devinitconst = {
+static const struct of_device_id pinmux_ids[] = {
{ .compatible = "sirf,prima2-pinctrl" },
+ { .compatible = "sirf,marco-pinctrl" },
{}
};
@@ -1621,8 +1642,8 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
spin_unlock_irqrestore(&bank->lock, flags);
}
-int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
+static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
{
struct sirfsoc_gpio_bank *bank = d->host_data;
@@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
struct sirfsoc_gpio_bank *bank;
void *regs;
struct platform_device *pdev;
+ bool is_marco = false;
pdev = of_find_device_by_node(np);
if (!pdev)
@@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
if (!regs)
return -ENOMEM;
+ if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+ is_marco = 1;
+
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
bank = &sgpio_bank[i];
spin_lock_init(&bank->lock);
@@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
bank->chip.gc.of_node = np;
bank->chip.regs = regs;
bank->id = i;
+ bank->is_marco = is_marco;
bank->parent_irq = platform_get_irq(pdev, i);
if (bank->parent_irq < 0) {
err = bank->parent_irq;
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 7da0b371fd65..e356b0380fa7 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -178,8 +178,9 @@ static int add_config(struct device *dev, unsigned long **configs,
return 0;
}
-void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map *map, unsigned num_maps)
+static void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map,
+ unsigned num_maps)
{
int i;
@@ -209,11 +210,11 @@ static const struct cfg_param {
{"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)
+static 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;
@@ -288,9 +289,10 @@ exit:
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)
+static 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;
@@ -660,7 +662,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
}
#endif
-struct pinconf_ops tegra_pinconf_ops = {
+static 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,
@@ -758,7 +760,7 @@ int __devinit tegra_pinctrl_probe(struct platform_device *pdev,
}
EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
-int __devexit tegra_pinctrl_remove(struct platform_device *pdev)
+int tegra_pinctrl_remove(struct platform_device *pdev)
{
struct tegra_pmx *pmx = platform_get_drvdata(pdev);
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
index a74f9a568536..1524bfd66602 100644
--- a/drivers/pinctrl/pinctrl-tegra20.c
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -2861,7 +2861,7 @@ static int __devinit tegra20_pinctrl_probe(struct platform_device *pdev)
return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
}
-static struct of_device_id tegra20_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id tegra20_pinctrl_of_match[] = {
{ .compatible = "nvidia,tegra20-pinmux", },
{ },
};
@@ -2873,7 +2873,7 @@ static struct platform_driver tegra20_pinctrl_driver = {
.of_match_table = tegra20_pinctrl_of_match,
},
.probe = tegra20_pinctrl_probe,
- .remove = __devexit_p(tegra_pinctrl_remove),
+ .remove = tegra_pinctrl_remove,
};
static int __init tegra20_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
index 7894f14c7059..cf579ebf346f 100644
--- a/drivers/pinctrl/pinctrl-tegra30.c
+++ b/drivers/pinctrl/pinctrl-tegra30.c
@@ -3727,7 +3727,7 @@ static int __devinit tegra30_pinctrl_probe(struct platform_device *pdev)
return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
}
-static struct of_device_id tegra30_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id tegra30_pinctrl_of_match[] = {
{ .compatible = "nvidia,tegra30-pinmux", },
{ },
};
@@ -3739,7 +3739,7 @@ static struct platform_driver tegra30_pinctrl_driver = {
.of_match_table = tegra30_pinctrl_of_match,
},
.probe = tegra30_pinctrl_probe,
- .remove = __devexit_p(tegra_pinctrl_remove),
+ .remove = tegra_pinctrl_remove,
};
static int __init tegra30_pinctrl_init(void)
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 309f5b9a70ec..8c039ad22baf 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = {
struct u300_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
- u32 phybase;
- u32 physize;
void __iomem *virtbase;
};
@@ -1013,52 +1011,11 @@ static struct pinmux_ops u300_pmx_ops = {
.disable = u300_pmx_disable,
};
-/*
- * GPIO ranges handled by the application-side COH901XXX GPIO controller
- * Very many pins can be converted into GPIO pins, but we only list those
- * that are useful in practice to cut down on tables.
- */
-#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \
- .pin_base = b, .npins = c }
-
-static struct pinctrl_gpio_range u300_gpio_ranges[] = {
- U300_GPIO_RANGE(10, 426, 1),
- U300_GPIO_RANGE(11, 180, 1),
- U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */
- U300_GPIO_RANGE(13, 179, 1),
- U300_GPIO_RANGE(14, 178, 1),
- U300_GPIO_RANGE(16, 194, 1),
- U300_GPIO_RANGE(17, 193, 1),
- U300_GPIO_RANGE(18, 192, 1),
- U300_GPIO_RANGE(19, 191, 1),
- U300_GPIO_RANGE(20, 186, 1),
- U300_GPIO_RANGE(21, 185, 1),
- U300_GPIO_RANGE(22, 184, 1),
- U300_GPIO_RANGE(23, 183, 1),
- U300_GPIO_RANGE(24, 182, 1),
- U300_GPIO_RANGE(25, 181, 1),
-};
-
-static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
- struct pinctrl_gpio_range *range;
-
- range = &u300_gpio_ranges[i];
- if (pin >= range->pin_base &&
- pin <= (range->pin_base + range->npins - 1))
- return range;
- }
- return NULL;
-}
-
-int u300_pin_config_get(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long *config)
+static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config)
{
- struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+ struct pinctrl_gpio_range *range =
+ pinctrl_find_gpio_range_from_pin(pctldev, pin);
/* We get config for those pins we CAN get it for and that's it */
if (!range)
@@ -1069,11 +1026,11 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev,
config);
}
-int u300_pin_config_set(struct pinctrl_dev *pctldev,
- unsigned pin,
- unsigned long config)
+static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long config)
{
- struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+ struct pinctrl_gpio_range *range =
+ pinctrl_find_gpio_range_from_pin(pctldev, pin);
int ret;
if (!range)
@@ -1109,9 +1066,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
{
struct u300_pmx *upmx;
struct resource *res;
- struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
- int ret;
- int i;
/* Create state holders etc for this driver */
upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
@@ -1123,32 +1077,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
- upmx->phybase = res->start;
- upmx->physize = resource_size(res);
-
- if (request_mem_region(upmx->phybase, upmx->physize,
- DRIVER_NAME) == NULL) {
- ret = -ENOMEM;
- goto out_no_memregion;
- }
- upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
- if (!upmx->virtbase) {
- ret = -ENOMEM;
- goto out_no_remap;
- }
+ upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res);
+ if (!upmx->virtbase)
+ return -ENOMEM;
upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
if (!upmx->pctl) {
dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
- ret = -EINVAL;
- goto out_no_pmx;
- }
-
- /* We will handle a range of GPIO pins */
- for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
- u300_gpio_ranges[i].gc = gpio_chip;
- pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
+ return -EINVAL;
}
platform_set_drvdata(pdev, upmx);
@@ -1156,23 +1093,13 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "initialized U300 pin control driver\n");
return 0;
-
-out_no_pmx:
- iounmap(upmx->virtbase);
-out_no_remap:
- platform_set_drvdata(pdev, NULL);
-out_no_memregion:
- release_mem_region(upmx->phybase, upmx->physize);
- return ret;
}
-static int __devexit u300_pmx_remove(struct platform_device *pdev)
+static int u300_pmx_remove(struct platform_device *pdev)
{
struct u300_pmx *upmx = platform_get_drvdata(pdev);
pinctrl_unregister(upmx->pctl);
- iounmap(upmx->virtbase);
- release_mem_region(upmx->phybase, upmx->physize);
platform_set_drvdata(pdev, NULL);
return 0;
@@ -1184,7 +1111,7 @@ static struct platform_driver u300_pmx_driver = {
.owner = THIS_MODULE,
},
.probe = u300_pmx_probe,
- .remove = __devexit_p(u300_pmx_remove),
+ .remove = u300_pmx_remove,
};
static int __init u300_pmx_init(void)
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index b9bcaec66223..ad90984ec500 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -522,7 +522,7 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev,
return 0;
}
-struct pinconf_ops xway_pinconf_ops = {
+static struct pinconf_ops xway_pinconf_ops = {
.pin_config_get = xway_pinconf_get,
.pin_config_set = xway_pinconf_set,
};
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 9301a7a95eff..1a00658b3ea0 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
char const * const *groups;
unsigned num_groups;
int ret;
const char *group;
int i;
- const unsigned *pins;
- unsigned num_pins;
if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n");
@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
}
setting->data.mux.group = ret;
- ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
- &num_pins);
- if (ret) {
- dev_err(pctldev->dev,
- "could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->data.mux.group);
- return -ENODEV;
- }
-
- /* Try to allocate all pins in this group, one by one */
- for (i = 0; i < num_pins; i++) {
- ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
- if (ret) {
- dev_err(pctldev->dev,
- "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 */
- for (; i >= 0; i--)
- pin_free(pctldev, pins[i], NULL);
- return -ENODEV;
- }
- }
-
return 0;
}
void pinmux_free_setting(struct pinctrl_setting const *setting)
{
- struct pinctrl_dev *pctldev = setting->pctldev;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const unsigned *pins;
- unsigned num_pins;
- int ret;
- int i;
-
- ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
- &pins, &num_pins);
- if (ret) {
- dev_err(pctldev->dev,
- "could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->data.mux.group);
- return;
- }
-
- for (i = 0; i < num_pins; i++)
- pin_free(pctldev, pins[i], NULL);
+ /* This function is currently unused */
}
int pinmux_enable_setting(struct pinctrl_setting const *setting)
@@ -446,6 +402,18 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
+ /* Try to allocate all pins in this group, one by one */
+ for (i = 0; i < num_pins; i++) {
+ ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
+ if (ret) {
+ dev_err(pctldev->dev,
+ "could not request pin %d on device %s\n",
+ pins[i], pinctrl_dev_get_name(pctldev));
+ goto err_pin_request;
+ }
+ }
+
+ /* Now that we have acquired the pins, encode the mux setting */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@@ -457,8 +425,26 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = &(setting->data.mux);
}
- return ops->enable(pctldev, setting->data.mux.func,
- setting->data.mux.group);
+ ret = ops->enable(pctldev, setting->data.mux.func,
+ setting->data.mux.group);
+
+ if (ret)
+ goto err_enable;
+
+ return 0;
+
+err_enable:
+ for (i = 0; i < num_pins; i++) {
+ desc = pin_desc_get(pctldev, pins[i]);
+ if (desc)
+ desc->mux_setting = NULL;
+ }
+err_pin_request:
+ /* On error release all taken pins */
+ while (--i >= 0)
+ pin_free(pctldev, pins[i], NULL);
+
+ return ret;
}
void pinmux_disable_setting(struct pinctrl_setting const *setting)
@@ -482,6 +468,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
+ /* Flag the descs that no setting is active */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@@ -493,6 +480,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = NULL;
}
+ /* And release the pins */
+ for (i = 0; i < num_pins; i++)
+ pin_free(pctldev, pins[i], NULL);
+
if (ops->disable)
ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}
diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 91558791e766..04d93e602674 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -25,20 +25,31 @@ config PINCTRL_SPEAR310
bool "ST Microelectronics SPEAr310 SoC pin controller driver"
depends on MACH_SPEAR310
select PINCTRL_SPEAR3XX
+ select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR320
bool "ST Microelectronics SPEAr320 SoC pin controller driver"
depends on MACH_SPEAR320
select PINCTRL_SPEAR3XX
+ select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1310
bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
depends on MACH_SPEAR1310
select PINCTRL_SPEAR
+ select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1340
bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
depends on MACH_SPEAR1340
select PINCTRL_SPEAR
+ select PINCTRL_SPEAR_PLGPIO
+
+config PINCTRL_SPEAR_PLGPIO
+ bool "SPEAr SoC PLGPIO Controller"
+ depends on GPIOLIB && PINCTRL_SPEAR
+ help
+ Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
+ SoCs.
endif
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index b28a7ba22443..0e400ebeb8ff 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -1,5 +1,6 @@
# SPEAr pinmux support
+obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO) += pinctrl-plgpio.o
obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
new file mode 100644
index 000000000000..4c045053bbdd
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -0,0 +1,758 @@
+/*
+ * SPEAr platform PLGPIO driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@linaro.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/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/spinlock.h>
+#include <asm/mach/irq.h>
+
+#define MAX_GPIO_PER_REG 32
+#define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG)
+#define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \
+ * sizeof(int *))
+
+/*
+ * plgpio pins in all machines are not one to one mapped, bitwise with registers
+ * bits. These set of macros define register masks for which below functions
+ * (pin_to_offset and offset_to_pin) are required to be called.
+ */
+#define PTO_ENB_REG 0x001
+#define PTO_WDATA_REG 0x002
+#define PTO_DIR_REG 0x004
+#define PTO_IE_REG 0x008
+#define PTO_RDATA_REG 0x010
+#define PTO_MIS_REG 0x020
+
+struct plgpio_regs {
+ u32 enb; /* enable register */
+ u32 wdata; /* write data register */
+ u32 dir; /* direction set register */
+ u32 rdata; /* read data register */
+ u32 ie; /* interrupt enable register */
+ u32 mis; /* mask interrupt status register */
+ u32 eit; /* edge interrupt type */
+};
+
+/*
+ * struct plgpio: plgpio driver specific structure
+ *
+ * lock: lock for guarding gpio registers
+ * base: base address of plgpio block
+ * irq_base: irq number of plgpio0
+ * chip: gpio framework specific chip information structure
+ * p2o: function ptr for pin to offset conversion. This is required only for
+ * machines where mapping b/w pin and offset is not 1-to-1.
+ * o2p: function ptr for offset to pin conversion. This is required only for
+ * machines where mapping b/w pin and offset is not 1-to-1.
+ * p2o_regs: mask of registers for which p2o and o2p are applicable
+ * regs: register offsets
+ * csave_regs: context save registers for standby/sleep/hibernate cases
+ */
+struct plgpio {
+ spinlock_t lock;
+ void __iomem *base;
+ struct clk *clk;
+ unsigned irq_base;
+ struct irq_domain *irq_domain;
+ struct gpio_chip chip;
+ int (*p2o)(int pin); /* pin_to_offset */
+ int (*o2p)(int offset); /* offset_to_pin */
+ u32 p2o_regs;
+ struct plgpio_regs regs;
+#ifdef CONFIG_PM
+ struct plgpio_regs *csave_regs;
+#endif
+};
+
+/* register manipulation inline functions */
+static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+{
+ u32 offset = PIN_OFFSET(pin);
+ void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+ u32 val = readl_relaxed(reg_off);
+
+ return !!(val & (1 << offset));
+}
+
+static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+{
+ u32 offset = PIN_OFFSET(pin);
+ void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+ u32 val = readl_relaxed(reg_off);
+
+ writel_relaxed(val | (1 << offset), reg_off);
+}
+
+static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+{
+ u32 offset = PIN_OFFSET(pin);
+ void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+ u32 val = readl_relaxed(reg_off);
+
+ writel_relaxed(val & ~(1 << offset), reg_off);
+}
+
+/* gpio framework specific routines */
+static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+ unsigned long flags;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+
+ return 0;
+}
+
+static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+ unsigned long flags;
+ unsigned dir_offset = offset, wdata_offset = offset, tmp;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
+ tmp = plgpio->p2o(offset);
+ if (tmp == -1)
+ return -EINVAL;
+
+ if (plgpio->p2o_regs & PTO_DIR_REG)
+ dir_offset = tmp;
+ if (plgpio->p2o_regs & PTO_WDATA_REG)
+ wdata_offset = tmp;
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ if (value)
+ plgpio_reg_set(plgpio->base, wdata_offset,
+ plgpio->regs.wdata);
+ else
+ plgpio_reg_reset(plgpio->base, wdata_offset,
+ plgpio->regs.wdata);
+
+ plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+
+ return 0;
+}
+
+static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+ if (offset >= chip->ngpio)
+ return -EINVAL;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return -EINVAL;
+ }
+
+ return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+}
+
+static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+ if (offset >= chip->ngpio)
+ return;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return;
+ }
+
+ if (value)
+ plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+ else
+ plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+}
+
+static int plgpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+ int gpio = chip->base + offset;
+ unsigned long flags;
+ int ret = 0;
+
+ if (offset >= chip->ngpio)
+ return -EINVAL;
+
+ ret = pinctrl_request_gpio(gpio);
+ if (ret)
+ return ret;
+
+ if (!IS_ERR(plgpio->clk)) {
+ ret = clk_enable(plgpio->clk);
+ if (ret)
+ goto err0;
+ }
+
+ if (plgpio->regs.enb == -1)
+ return 0;
+
+ /*
+ * put gpio in IN mode before enabling it. This make enabling gpio safe
+ */
+ ret = plgpio_direction_input(chip, offset);
+ if (ret)
+ goto err1;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1) {
+ ret = -EINVAL;
+ goto err1;
+ }
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+ return 0;
+
+err1:
+ if (!IS_ERR(plgpio->clk))
+ clk_disable(plgpio->clk);
+err0:
+ pinctrl_free_gpio(gpio);
+ return ret;
+}
+
+static void plgpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+ int gpio = chip->base + offset;
+ unsigned long flags;
+
+ if (offset >= chip->ngpio)
+ return;
+
+ if (plgpio->regs.enb == -1)
+ goto disable_clk;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return;
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+
+disable_clk:
+ if (!IS_ERR(plgpio->clk))
+ clk_disable(plgpio->clk);
+
+ pinctrl_free_gpio(gpio);
+}
+
+static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+ if (IS_ERR_VALUE(plgpio->irq_base))
+ return -EINVAL;
+
+ return irq_find_mapping(plgpio->irq_domain, offset);
+}
+
+/* PLGPIO IRQ */
+static void plgpio_irq_disable(struct irq_data *d)
+{
+ struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+ int offset = d->irq - plgpio->irq_base;
+ unsigned long flags;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return;
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static void plgpio_irq_enable(struct irq_data *d)
+{
+ struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+ int offset = d->irq - plgpio->irq_base;
+ unsigned long flags;
+
+ /* get correct offset for "offset" pin */
+ if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+ offset = plgpio->p2o(offset);
+ if (offset == -1)
+ return;
+ }
+
+ spin_lock_irqsave(&plgpio->lock, flags);
+ plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+ spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+ struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+ int offset = d->irq - plgpio->irq_base;
+ void __iomem *reg_off;
+ unsigned int supported_type = 0, val;
+
+ if (offset >= plgpio->chip.ngpio)
+ return -EINVAL;
+
+ if (plgpio->regs.eit == -1)
+ supported_type = IRQ_TYPE_LEVEL_HIGH;
+ else
+ supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+ if (!(trigger & supported_type))
+ return -EINVAL;
+
+ if (plgpio->regs.eit == -1)
+ return 0;
+
+ reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
+ val = readl_relaxed(reg_off);
+
+ offset = PIN_OFFSET(offset);
+ if (trigger & IRQ_TYPE_EDGE_RISING)
+ writel_relaxed(val | (1 << offset), reg_off);
+ else
+ writel_relaxed(val & ~(1 << offset), reg_off);
+
+ return 0;
+}
+
+static struct irq_chip plgpio_irqchip = {
+ .name = "PLGPIO",
+ .irq_enable = plgpio_irq_enable,
+ .irq_disable = plgpio_irq_disable,
+ .irq_set_type = plgpio_irq_set_type,
+};
+
+static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ struct plgpio *plgpio = irq_get_handler_data(irq);
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
+ int regs_count, count, pin, offset, i = 0;
+ unsigned long pending;
+
+ count = plgpio->chip.ngpio;
+ regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
+
+ chained_irq_enter(irqchip, desc);
+ /* check all plgpio MIS registers for a possible interrupt */
+ for (; i < regs_count; i++) {
+ pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
+ i * sizeof(int *));
+ if (!pending)
+ continue;
+
+ /* clear interrupts */
+ writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
+ i * sizeof(int *));
+ /*
+ * clear extra bits in last register having gpios < MAX/REG
+ * ex: Suppose there are max 102 plgpios. then last register
+ * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
+ * so, we must not take other 28 bits into consideration for
+ * checking interrupt. so clear those bits.
+ */
+ count = count - i * MAX_GPIO_PER_REG;
+ if (count < MAX_GPIO_PER_REG)
+ pending &= (1 << count) - 1;
+
+ for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+ /* get correct pin for "offset" */
+ if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
+ pin = plgpio->o2p(offset);
+ if (pin == -1)
+ continue;
+ } else
+ pin = offset;
+
+ /* get correct irq line number */
+ pin = i * MAX_GPIO_PER_REG + pin;
+ generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+ }
+ }
+ chained_irq_exit(irqchip, desc);
+}
+
+/*
+ * pin to offset and offset to pin converter functions
+ *
+ * In spear310 there is inconsistency among bit positions in plgpio regiseters,
+ * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
+ * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
+ */
+static int spear310_p2o(int pin)
+{
+ int offset = pin;
+
+ if (pin <= 27)
+ offset += 4;
+ else if (pin <= 33)
+ offset = -1;
+ else if (pin <= 97)
+ offset -= 2;
+ else if (pin <= 101)
+ offset = 101 - pin;
+ else
+ offset = -1;
+
+ return offset;
+}
+
+int spear310_o2p(int offset)
+{
+ if (offset <= 3)
+ return 101 - offset;
+ else if (offset <= 31)
+ return offset - 4;
+ else
+ return offset + 2;
+}
+
+static int __devinit plgpio_probe_dt(struct platform_device *pdev,
+ struct plgpio *plgpio)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret = -EINVAL;
+ u32 val;
+
+ if (of_machine_is_compatible("st,spear310")) {
+ plgpio->p2o = spear310_p2o;
+ plgpio->o2p = spear310_o2p;
+ plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
+ PTO_RDATA_REG | PTO_MIS_REG;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
+ plgpio->chip.ngpio = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
+ plgpio->regs.enb = val;
+ else
+ plgpio->regs.enb = -1;
+
+ if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
+ plgpio->regs.wdata = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
+ plgpio->regs.dir = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid dir reg\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
+ plgpio->regs.ie = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid ie reg\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
+ plgpio->regs.rdata = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
+ plgpio->regs.mis = val;
+ } else {
+ dev_err(&pdev->dev, "DT: Invalid mis reg\n");
+ goto end;
+ }
+
+ if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
+ plgpio->regs.eit = val;
+ else
+ plgpio->regs.eit = -1;
+
+ return 0;
+
+end:
+ return ret;
+}
+static int __devinit plgpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct plgpio *plgpio;
+ struct resource *res;
+ int ret, irq, i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+ return -EBUSY;
+ }
+
+ plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
+ if (!plgpio) {
+ dev_err(&pdev->dev, "memory allocation fail\n");
+ return -ENOMEM;
+ }
+
+ plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!plgpio->base) {
+ dev_err(&pdev->dev, "request and ioremap fail\n");
+ return -ENOMEM;
+ }
+
+ ret = plgpio_probe_dt(pdev, plgpio);
+ if (ret) {
+ dev_err(&pdev->dev, "DT probe failed\n");
+ return ret;
+ }
+
+ plgpio->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(plgpio->clk))
+ dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
+
+#ifdef CONFIG_PM
+ plgpio->csave_regs = devm_kzalloc(&pdev->dev,
+ sizeof(*plgpio->csave_regs) *
+ DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+ GFP_KERNEL);
+ if (!plgpio->csave_regs) {
+ dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+ return -ENOMEM;
+ }
+#endif
+
+ platform_set_drvdata(pdev, plgpio);
+ spin_lock_init(&plgpio->lock);
+
+ plgpio->irq_base = -1;
+ plgpio->chip.base = -1;
+ plgpio->chip.request = plgpio_request;
+ plgpio->chip.free = plgpio_free;
+ plgpio->chip.direction_input = plgpio_direction_input;
+ plgpio->chip.direction_output = plgpio_direction_output;
+ plgpio->chip.get = plgpio_get_value;
+ plgpio->chip.set = plgpio_set_value;
+ plgpio->chip.to_irq = plgpio_to_irq;
+ plgpio->chip.label = dev_name(&pdev->dev);
+ plgpio->chip.dev = &pdev->dev;
+ plgpio->chip.owner = THIS_MODULE;
+
+ if (!IS_ERR(plgpio->clk)) {
+ ret = clk_prepare(plgpio->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "clk prepare failed\n");
+ return ret;
+ }
+ }
+
+ ret = gpiochip_add(&plgpio->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to add gpio chip\n");
+ goto unprepare_clk;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_info(&pdev->dev, "irqs not supported\n");
+ return 0;
+ }
+
+ plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
+ if (IS_ERR_VALUE(plgpio->irq_base)) {
+ /* we would not support irq for gpio */
+ dev_warn(&pdev->dev, "couldn't allocate irq base\n");
+ return 0;
+ }
+
+ plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
+ plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
+ if (WARN_ON(!plgpio->irq_domain)) {
+ dev_err(&pdev->dev, "irq domain init failed\n");
+ irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
+ ret = -ENXIO;
+ goto remove_gpiochip;
+ }
+
+ irq_set_chained_handler(irq, plgpio_irq_handler);
+ for (i = 0; i < plgpio->chip.ngpio; i++) {
+ irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
+ handle_simple_irq);
+ set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
+ irq_set_chip_data(i + plgpio->irq_base, plgpio);
+ }
+
+ irq_set_handler_data(irq, plgpio);
+ dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
+
+ return 0;
+
+remove_gpiochip:
+ dev_info(&pdev->dev, "Remove gpiochip\n");
+ if (gpiochip_remove(&plgpio->chip))
+ dev_err(&pdev->dev, "unable to remove gpiochip\n");
+unprepare_clk:
+ if (!IS_ERR(plgpio->clk))
+ clk_unprepare(plgpio->clk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int plgpio_suspend(struct device *dev)
+{
+ struct plgpio *plgpio = dev_get_drvdata(dev);
+ int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+ void __iomem *off;
+
+ for (i = 0; i < reg_count; i++) {
+ off = plgpio->base + i * sizeof(int *);
+
+ if (plgpio->regs.enb != -1)
+ plgpio->csave_regs[i].enb =
+ readl_relaxed(plgpio->regs.enb + off);
+ if (plgpio->regs.eit != -1)
+ plgpio->csave_regs[i].eit =
+ readl_relaxed(plgpio->regs.eit + off);
+ plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
+ off);
+ plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
+ off);
+ plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+ }
+
+ return 0;
+}
+
+/*
+ * This is used to correct the values in end registers. End registers contain
+ * extra bits that might be used for other purpose in platform. So, we shouldn't
+ * overwrite these bits. This macro, reads given register again, preserves other
+ * bit values (non-plgpio bits), and retain captured value (plgpio bits).
+ */
+#define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \
+{ \
+ _tmp = readl_relaxed(plgpio->regs.__reg + _off); \
+ _tmp &= ~_mask; \
+ plgpio->csave_regs[i].__reg = \
+ _tmp | (plgpio->csave_regs[i].__reg & _mask); \
+}
+
+static int plgpio_resume(struct device *dev)
+{
+ struct plgpio *plgpio = dev_get_drvdata(dev);
+ int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+ void __iomem *off;
+ u32 mask, tmp;
+
+ for (i = 0; i < reg_count; i++) {
+ off = plgpio->base + i * sizeof(int *);
+
+ if (i == reg_count - 1) {
+ mask = (1 << (plgpio->chip.ngpio - i *
+ MAX_GPIO_PER_REG)) - 1;
+
+ if (plgpio->regs.enb != -1)
+ plgpio_prepare_reg(enb, off, mask, tmp);
+
+ if (plgpio->regs.eit != -1)
+ plgpio_prepare_reg(eit, off, mask, tmp);
+
+ plgpio_prepare_reg(wdata, off, mask, tmp);
+ plgpio_prepare_reg(dir, off, mask, tmp);
+ plgpio_prepare_reg(ie, off, mask, tmp);
+ }
+
+ writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
+ off);
+ writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
+ off);
+
+ if (plgpio->regs.eit != -1)
+ writel_relaxed(plgpio->csave_regs[i].eit,
+ plgpio->regs.eit + off);
+
+ writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+
+ if (plgpio->regs.enb != -1)
+ writel_relaxed(plgpio->csave_regs[i].enb,
+ plgpio->regs.enb + off);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
+
+static const struct of_device_id plgpio_of_match[] = {
+ { .compatible = "st,spear-plgpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, plgpio_of_match);
+
+static struct platform_driver plgpio_driver = {
+ .probe = plgpio_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "spear-plgpio",
+ .pm = &plgpio_dev_pm_ops,
+ .of_match_table = of_match_ptr(plgpio_of_match),
+ },
+};
+
+static int __init plgpio_init(void)
+{
+ return platform_driver_register(&plgpio_driver);
+}
+subsys_initcall(plgpio_init);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index b1fd6ee33c6c..922c057521a1 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -14,10 +14,10 @@
*/
#include <linux/err.h>
-#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_gpio.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
@@ -28,14 +28,26 @@
#define DRIVER_NAME "spear-pinmux"
-static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+static void muxregs_endisable(struct spear_pmx *pmx,
+ struct spear_muxreg *muxregs, u8 count, bool enable)
{
- return readl_relaxed(pmx->vbase + reg);
-}
+ struct spear_muxreg *muxreg;
+ u32 val, temp, j;
-static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
-{
- writel_relaxed(val, pmx->vbase + reg);
+ for (j = 0; j < count; j++) {
+ muxreg = &muxregs[j];
+
+ val = pmx_readl(pmx, muxreg->reg);
+ val &= ~muxreg->mask;
+
+ if (enable)
+ temp = muxreg->val;
+ else
+ temp = ~muxreg->val;
+
+ val |= muxreg->mask & temp;
+ pmx_writel(pmx, val, muxreg->reg);
+ }
}
static int set_mode(struct spear_pmx *pmx, int mode)
@@ -70,6 +82,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
return 0;
}
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+ unsigned count, u16 reg)
+{
+ int i, j;
+
+ for (i = 0; i < count; i++)
+ for (j = 0; j < gpio_pingroup[i].nmuxregs; j++)
+ gpio_pingroup[i].muxregs[j].reg = reg;
+}
+
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
{
struct spear_pingroup *pgroup;
@@ -121,9 +144,10 @@ static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
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)
+static 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;
@@ -168,8 +192,9 @@ int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
return 0;
}
-void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map *map, unsigned num_maps)
+static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map,
+ unsigned num_maps)
{
kfree(map);
}
@@ -216,9 +241,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
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;
+ int i;
bool found = false;
pgroup = pmx->machdata->groups[group];
@@ -233,20 +256,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
}
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 |= muxreg->mask & temp;
- pmx_writel(pmx, val, muxreg->reg);
- }
+ muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
+ enable);
}
if (!found) {
@@ -270,12 +281,74 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
spear_pinctrl_endisable(pctldev, function, group, false);
}
+/* gpio with pinmux */
+static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
+ unsigned pin)
+{
+ struct spear_gpio_pingroup *gpio_pingroup;
+ int i, j;
+
+ if (!pmx->machdata->gpio_pingroups)
+ return NULL;
+
+ for (i = 0; i < pmx->machdata->ngpio_pingroups; i++) {
+ gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
+
+ for (j = 0; j < gpio_pingroup->npins; j++) {
+ if (gpio_pingroup->pins[j] == pin)
+ return gpio_pingroup;
+ }
+ }
+
+ return NULL;
+}
+
+static int gpio_request_endisable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset, bool enable)
+{
+ struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+ struct spear_pinctrl_machdata *machdata = pmx->machdata;
+ struct spear_gpio_pingroup *gpio_pingroup;
+
+ /*
+ * Some SoC have configuration options applicable to group of pins,
+ * rather than a single pin.
+ */
+ gpio_pingroup = get_gpio_pingroup(pmx, offset);
+ if (gpio_pingroup)
+ muxregs_endisable(pmx, gpio_pingroup->muxregs,
+ gpio_pingroup->nmuxregs, enable);
+
+ /*
+ * SoC may need some extra configurations, or configurations for single
+ * pin
+ */
+ if (machdata->gpio_request_endisable)
+ machdata->gpio_request_endisable(pmx, offset, enable);
+
+ return 0;
+}
+
+static int gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset)
+{
+ return gpio_request_endisable(pctldev, range, offset, true);
+}
+
+static void gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned offset)
+{
+ gpio_request_endisable(pctldev, range, offset, 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,
+ .gpio_request_enable = gpio_request_enable,
+ .gpio_disable_free = gpio_disable_free,
};
static struct pinctrl_desc spear_pinctrl_desc = {
@@ -344,7 +417,7 @@ int __devinit spear_pinctrl_probe(struct platform_device *pdev,
return 0;
}
-int __devexit spear_pinctrl_remove(struct platform_device *pdev)
+int spear_pinctrl_remove(struct platform_device *pdev)
{
struct spear_pmx *pmx = platform_get_drvdata(pdev);
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
index d950eb78d939..1be46ecc6d91 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.h
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -12,11 +12,14 @@
#ifndef __PINMUX_SPEAR_H__
#define __PINMUX_SPEAR_H__
+#include <linux/gpio.h>
+#include <linux/io.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/types.h>
struct platform_device;
struct device;
+struct spear_pmx;
/**
* struct spear_pmx_mode - SPEAr pmx mode
@@ -46,6 +49,44 @@ struct spear_muxreg {
u32 val;
};
+struct spear_gpio_pingroup {
+ const unsigned *pins;
+ unsigned npins;
+ struct spear_muxreg *muxregs;
+ u8 nmuxregs;
+};
+
+/* ste: set to enable */
+#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste) \
+static struct spear_muxreg __pins##_muxregs[] = { \
+ { \
+ .reg = __muxreg, \
+ .mask = __mask, \
+ .val = __ste ? __mask : 0, \
+ }, \
+}
+
+#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
+static struct spear_muxreg __pins##_muxregs[] = { \
+ { \
+ .reg = __muxreg1, \
+ .mask = __mask, \
+ .val = __ste1 ? __mask : 0, \
+ }, { \
+ .reg = __muxreg2, \
+ .mask = __mask, \
+ .val = __ste2 ? __mask : 0, \
+ }, \
+}
+
+#define GPIO_PINGROUP(__pins) \
+ { \
+ .pins = __pins, \
+ .npins = ARRAY_SIZE(__pins), \
+ .muxregs = __pins##_muxregs, \
+ .nmuxregs = ARRAY_SIZE(__pins##_muxregs), \
+ }
+
/**
* struct spear_modemux - SPEAr mode mux configuration
* @modes: mode ids supported by this group of muxregs
@@ -100,6 +141,8 @@ struct spear_function {
* @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.
+ * @gpio_pingroups: gpio pingroups
+ * @ngpio_pingroups: gpio pingroups count
*
* @modes_supported: Does SoC support modes
* @mode: mode configured from probe
@@ -113,6 +156,10 @@ struct spear_pinctrl_machdata {
unsigned nfunctions;
struct spear_pingroup **groups;
unsigned ngroups;
+ struct spear_gpio_pingroup *gpio_pingroups;
+ void (*gpio_request_endisable)(struct spear_pmx *pmx, int offset,
+ bool enable);
+ unsigned ngpio_pingroups;
bool modes_supported;
u16 mode;
@@ -135,10 +182,23 @@ struct spear_pmx {
};
/* exported routines */
+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);
+}
+
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+ unsigned count, 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);
+int spear_pinctrl_remove(struct platform_device *pdev);
#define SPEAR_PIN_0_TO_101 \
PINCTRL_PIN(0, "PLGPIO0"), \
diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index 0436fc7895d6..e40d785a3fc2 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -2418,6 +2418,268 @@ static struct spear_function *spear1310_functions[] = {
&gpt64_function,
};
+static const unsigned pin18[] = { 18, };
+static const unsigned pin19[] = { 19, };
+static const unsigned pin20[] = { 20, };
+static const unsigned pin21[] = { 21, };
+static const unsigned pin22[] = { 22, };
+static const unsigned pin23[] = { 23, };
+static const unsigned pin54[] = { 54, };
+static const unsigned pin55[] = { 55, };
+static const unsigned pin56[] = { 56, };
+static const unsigned pin57[] = { 57, };
+static const unsigned pin58[] = { 58, };
+static const unsigned pin59[] = { 59, };
+static const unsigned pin60[] = { 60, };
+static const unsigned pin61[] = { 61, };
+static const unsigned pin62[] = { 62, };
+static const unsigned pin63[] = { 63, };
+static const unsigned pin143[] = { 143, };
+static const unsigned pin144[] = { 144, };
+static const unsigned pin145[] = { 145, };
+static const unsigned pin146[] = { 146, };
+static const unsigned pin147[] = { 147, };
+static const unsigned pin148[] = { 148, };
+static const unsigned pin149[] = { 149, };
+static const unsigned pin150[] = { 150, };
+static const unsigned pin151[] = { 151, };
+static const unsigned pin152[] = { 152, };
+static const unsigned pin205[] = { 205, };
+static const unsigned pin206[] = { 206, };
+static const unsigned pin211[] = { 211, };
+static const unsigned pin212[] = { 212, };
+static const unsigned pin213[] = { 213, };
+static const unsigned pin214[] = { 214, };
+static const unsigned pin215[] = { 215, };
+static const unsigned pin216[] = { 216, };
+static const unsigned pin217[] = { 217, };
+static const unsigned pin218[] = { 218, };
+static const unsigned pin219[] = { 219, };
+static const unsigned pin220[] = { 220, };
+static const unsigned pin221[] = { 221, };
+static const unsigned pin222[] = { 222, };
+static const unsigned pin223[] = { 223, };
+static const unsigned pin224[] = { 224, };
+static const unsigned pin225[] = { 225, };
+static const unsigned pin226[] = { 226, };
+static const unsigned pin227[] = { 227, };
+static const unsigned pin228[] = { 228, };
+static const unsigned pin229[] = { 229, };
+static const unsigned pin230[] = { 230, };
+static const unsigned pin231[] = { 231, };
+static const unsigned pin232[] = { 232, };
+static const unsigned pin233[] = { 233, };
+static const unsigned pin234[] = { 234, };
+static const unsigned pin235[] = { 235, };
+static const unsigned pin236[] = { 236, };
+static const unsigned pin237[] = { 237, };
+static const unsigned pin238[] = { 238, };
+static const unsigned pin239[] = { 239, };
+static const unsigned pin240[] = { 240, };
+static const unsigned pin241[] = { 241, };
+static const unsigned pin242[] = { 242, };
+static const unsigned pin243[] = { 243, };
+static const unsigned pin244[] = { 244, };
+static const unsigned pin245[] = { 245, };
+
+static const unsigned pin_grp0[] = { 173, 174, };
+static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
+static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
+ 190, 191, 192, };
+static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
+static const unsigned pin_grp4[] = { 199, 200, };
+static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
+static const unsigned pin_grp7[] = { 98, 99, };
+static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
+ 166, 167, 168, 169, 170, 171, 172, };
+
+/* Define muxreg arrays */
+DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1);
+DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1);
+DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1);
+DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1);
+DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1);
+DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1);
+DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1);
+DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1);
+DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1);
+DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1);
+DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1);
+DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1);
+DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1);
+DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1);
+DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1);
+DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1);
+DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1);
+DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1);
+DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1);
+DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1);
+DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1);
+DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1);
+DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1);
+DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1);
+DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1);
+
+static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
+ GPIO_PINGROUP(i2c0_pins),
+ GPIO_PINGROUP(ssp0_pins),
+ GPIO_PINGROUP(ssp0_cs0_pins),
+ GPIO_PINGROUP(ssp0_cs1_2_pins),
+ GPIO_PINGROUP(i2s0_pins),
+ GPIO_PINGROUP(i2s1_pins),
+ GPIO_PINGROUP(clcd_pins),
+ GPIO_PINGROUP(clcd_high_res_pins),
+ GPIO_PINGROUP(pin18),
+ GPIO_PINGROUP(pin19),
+ GPIO_PINGROUP(pin20),
+ GPIO_PINGROUP(pin21),
+ GPIO_PINGROUP(pin22),
+ GPIO_PINGROUP(pin23),
+ GPIO_PINGROUP(pin143),
+ GPIO_PINGROUP(pin144),
+ GPIO_PINGROUP(pin145),
+ GPIO_PINGROUP(pin146),
+ GPIO_PINGROUP(pin147),
+ GPIO_PINGROUP(pin148),
+ GPIO_PINGROUP(pin149),
+ GPIO_PINGROUP(pin150),
+ GPIO_PINGROUP(pin151),
+ GPIO_PINGROUP(pin152),
+ GPIO_PINGROUP(smi_2_chips_pins),
+ GPIO_PINGROUP(pin54),
+ GPIO_PINGROUP(pin55),
+ GPIO_PINGROUP(pin56),
+ GPIO_PINGROUP(pin57),
+ GPIO_PINGROUP(pin58),
+ GPIO_PINGROUP(pin59),
+ GPIO_PINGROUP(pin60),
+ GPIO_PINGROUP(pin61),
+ GPIO_PINGROUP(pin62),
+ GPIO_PINGROUP(pin63),
+ GPIO_PINGROUP(pin_grp0),
+ GPIO_PINGROUP(pin_grp1),
+ GPIO_PINGROUP(pin_grp2),
+ GPIO_PINGROUP(pin_grp3),
+ GPIO_PINGROUP(pin_grp4),
+ GPIO_PINGROUP(pin_grp5),
+ GPIO_PINGROUP(pin_grp6),
+ GPIO_PINGROUP(pin_grp7),
+ GPIO_PINGROUP(pin_grp8),
+ GPIO_PINGROUP(nand_16bit_pins),
+ GPIO_PINGROUP(pin205),
+ GPIO_PINGROUP(pin206),
+ GPIO_PINGROUP(pin211),
+ GPIO_PINGROUP(pin212),
+ GPIO_PINGROUP(pin213),
+ GPIO_PINGROUP(pin214),
+ GPIO_PINGROUP(pin215),
+ GPIO_PINGROUP(pin216),
+ GPIO_PINGROUP(pin217),
+ GPIO_PINGROUP(pin218),
+ GPIO_PINGROUP(pin219),
+ GPIO_PINGROUP(pin220),
+ GPIO_PINGROUP(pin221),
+ GPIO_PINGROUP(pin222),
+ GPIO_PINGROUP(pin223),
+ GPIO_PINGROUP(pin224),
+ GPIO_PINGROUP(pin225),
+ GPIO_PINGROUP(pin226),
+ GPIO_PINGROUP(pin227),
+ GPIO_PINGROUP(pin228),
+ GPIO_PINGROUP(pin229),
+ GPIO_PINGROUP(pin230),
+ GPIO_PINGROUP(pin231),
+ GPIO_PINGROUP(pin232),
+ GPIO_PINGROUP(pin233),
+ GPIO_PINGROUP(pin234),
+ GPIO_PINGROUP(pin235),
+ GPIO_PINGROUP(pin236),
+ GPIO_PINGROUP(pin237),
+ GPIO_PINGROUP(pin238),
+ GPIO_PINGROUP(pin239),
+ GPIO_PINGROUP(pin240),
+ GPIO_PINGROUP(pin241),
+ GPIO_PINGROUP(pin242),
+ GPIO_PINGROUP(pin243),
+ GPIO_PINGROUP(pin244),
+ GPIO_PINGROUP(pin245),
+ GPIO_PINGROUP(keyboard_rowcol6_8_pins),
+ GPIO_PINGROUP(uart0_pins),
+ GPIO_PINGROUP(uart0_modem_pins),
+ GPIO_PINGROUP(gpt0_tmr0_pins),
+ GPIO_PINGROUP(gpt0_tmr1_pins),
+ GPIO_PINGROUP(gpt1_tmr0_pins),
+ GPIO_PINGROUP(gpt1_tmr1_pins),
+ GPIO_PINGROUP(touch_xy_pins),
+};
+
static struct spear_pinctrl_machdata spear1310_machdata = {
.pins = spear1310_pins,
.npins = ARRAY_SIZE(spear1310_pins),
@@ -2425,10 +2687,12 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
.ngroups = ARRAY_SIZE(spear1310_pingroups),
.functions = spear1310_functions,
.nfunctions = ARRAY_SIZE(spear1310_functions),
+ .gpio_pingroups = spear1310_gpio_pingroup,
+ .ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
.modes_supported = false,
};
-static struct of_device_id spear1310_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear1310_pinctrl_of_match[] = {
{
.compatible = "st,spear1310-pinmux",
},
@@ -2440,7 +2704,7 @@ static int __devinit spear1310_pinctrl_probe(struct platform_device *pdev)
return spear_pinctrl_probe(pdev, &spear1310_machdata);
}
-static int __devexit spear1310_pinctrl_remove(struct platform_device *pdev)
+static int spear1310_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
@@ -2452,7 +2716,7 @@ static struct platform_driver spear1310_pinctrl_driver = {
.of_match_table = spear1310_pinctrl_of_match,
},
.probe = spear1310_pinctrl_probe,
- .remove = __devexit_p(spear1310_pinctrl_remove),
+ .remove = spear1310_pinctrl_remove,
};
static int __init spear1310_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index 0606b8cf3f2c..8deaaff3156c 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -1971,6 +1971,32 @@ static struct spear_function *spear1340_functions[] = {
&sata_function,
};
+static void gpio_request_endisable(struct spear_pmx *pmx, int pin,
+ bool enable)
+{
+ unsigned int regoffset, regindex, bitoffset;
+ unsigned int val;
+
+ /* pin++ as gpio configuration starts from 2nd bit of base register */
+ pin++;
+
+ regindex = pin / 32;
+ bitoffset = pin % 32;
+
+ if (regindex <= 3)
+ regoffset = PAD_FUNCTION_EN_1 + regindex * sizeof(int *);
+ else
+ regoffset = PAD_FUNCTION_EN_5 + (regindex - 4) * sizeof(int *);
+
+ val = pmx_readl(pmx, regoffset);
+ if (enable)
+ val &= ~(0x1 << bitoffset);
+ else
+ val |= 0x1 << bitoffset;
+
+ pmx_writel(pmx, val, regoffset);
+}
+
static struct spear_pinctrl_machdata spear1340_machdata = {
.pins = spear1340_pins,
.npins = ARRAY_SIZE(spear1340_pins),
@@ -1978,10 +2004,11 @@ static struct spear_pinctrl_machdata spear1340_machdata = {
.ngroups = ARRAY_SIZE(spear1340_pingroups),
.functions = spear1340_functions,
.nfunctions = ARRAY_SIZE(spear1340_functions),
+ .gpio_request_endisable = gpio_request_endisable,
.modes_supported = false,
};
-static struct of_device_id spear1340_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear1340_pinctrl_of_match[] = {
{
.compatible = "st,spear1340-pinmux",
},
@@ -1993,7 +2020,7 @@ static int __devinit spear1340_pinctrl_probe(struct platform_device *pdev)
return spear_pinctrl_probe(pdev, &spear1340_machdata);
}
-static int __devexit spear1340_pinctrl_remove(struct platform_device *pdev)
+static int spear1340_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
@@ -2005,7 +2032,7 @@ static struct platform_driver spear1340_pinctrl_driver = {
.of_match_table = spear1340_pinctrl_of_match,
},
.probe = spear1340_pinctrl_probe,
- .remove = __devexit_p(spear1340_pinctrl_remove),
+ .remove = spear1340_pinctrl_remove,
};
static int __init spear1340_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
index 4dfc2849b172..f48e466e605a 100644
--- a/drivers/pinctrl/spear/pinctrl-spear300.c
+++ b/drivers/pinctrl/spear/pinctrl-spear300.c
@@ -646,7 +646,7 @@ static struct spear_function *spear300_functions[] = {
&gpio1_function,
};
-static struct of_device_id spear300_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear300_pinctrl_of_match[] = {
{
.compatible = "st,spear300-pinmux",
},
@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
spear3xx_machdata.functions = spear300_functions;
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+ spear3xx_machdata.gpio_pingroups = NULL;
+ spear3xx_machdata.ngpio_pingroups = 0;
spear3xx_machdata.modes_supported = true;
spear3xx_machdata.pmx_modes = spear300_pmx_modes;
@@ -675,7 +677,7 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit spear300_pinctrl_remove(struct platform_device *pdev)
+static int spear300_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
@@ -687,7 +689,7 @@ static struct platform_driver spear300_pinctrl_driver = {
.of_match_table = spear300_pinctrl_of_match,
},
.probe = spear300_pinctrl_probe,
- .remove = __devexit_p(spear300_pinctrl_remove),
+ .remove = spear300_pinctrl_remove,
};
static int __init spear300_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
index 96883693fb7e..5b954c19a6d2 100644
--- a/drivers/pinctrl/spear/pinctrl-spear310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear310.c
@@ -371,7 +371,7 @@ static struct spear_function *spear310_functions[] = {
&tdm_function,
};
-static struct of_device_id spear310_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear310_pinctrl_of_match[] = {
{
.compatible = "st,spear310-pinmux",
},
@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+ pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+ spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
spear3xx_machdata.modes_supported = false;
@@ -398,7 +400,7 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit spear310_pinctrl_remove(struct platform_device *pdev)
+static int spear310_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
@@ -410,7 +412,7 @@ static struct platform_driver spear310_pinctrl_driver = {
.of_match_table = spear310_pinctrl_of_match,
},
.probe = spear310_pinctrl_probe,
- .remove = __devexit_p(spear310_pinctrl_remove),
+ .remove = spear310_pinctrl_remove,
};
static int __init spear310_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
index ca47b0e50780..e9a5e6d39242 100644
--- a/drivers/pinctrl/spear/pinctrl-spear320.c
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -3410,7 +3410,7 @@ static struct spear_function *spear320_functions[] = {
&i2c2_function,
};
-static struct of_device_id spear320_pinctrl_of_match[] __devinitdata = {
+static struct of_device_id spear320_pinctrl_of_match[] = {
{
.compatible = "st,spear320-pinmux",
},
@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+ pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+ spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret)
@@ -3439,7 +3441,7 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit spear320_pinctrl_remove(struct platform_device *pdev)
+static int spear320_pinctrl_remove(struct platform_device *pdev)
{
return spear_pinctrl_remove(pdev);
}
@@ -3451,7 +3453,7 @@ static struct platform_driver spear320_pinctrl_driver = {
.of_match_table = spear320_pinctrl_of_match,
},
.probe = spear320_pinctrl_probe,
- .remove = __devexit_p(spear320_pinctrl_remove),
+ .remove = spear320_pinctrl_remove,
};
static int __init spear320_pinctrl_init(void)
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c
index 0242378f7cb8..12ee21af766b 100644
--- a/drivers/pinctrl/spear/pinctrl-spear3xx.c
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c
@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
.ngroups = ARRAY_SIZE(timer_2_3_grps),
};
+/* Define muxreg arrays */
+DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
+DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
+DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
+DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
+DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
+DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
+DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
+DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
+DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
+DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
+DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
+DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
+DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
+DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
+DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
+
+static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
+ GPIO_PINGROUP(firda_pins),
+ GPIO_PINGROUP(i2c_pins),
+ GPIO_PINGROUP(ssp_cs_pins),
+ GPIO_PINGROUP(ssp_pins),
+ GPIO_PINGROUP(mii_pins),
+ GPIO_PINGROUP(gpio0_pin0_pins),
+ GPIO_PINGROUP(gpio0_pin1_pins),
+ GPIO_PINGROUP(gpio0_pin2_pins),
+ GPIO_PINGROUP(gpio0_pin3_pins),
+ GPIO_PINGROUP(gpio0_pin4_pins),
+ GPIO_PINGROUP(gpio0_pin5_pins),
+ GPIO_PINGROUP(uart0_ext_pins),
+ GPIO_PINGROUP(uart0_pins),
+ GPIO_PINGROUP(timer_0_1_pins),
+ GPIO_PINGROUP(timer_2_3_pins),
+};
+
struct spear_pinctrl_machdata spear3xx_machdata = {
.pins = spear3xx_pins,
.npins = ARRAY_SIZE(spear3xx_pins),
+ .gpio_pingroups = spear3xx_gpio_pingroup,
+ .ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
};
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index fa4e0a5db3f8..ffd53e3eb92f 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -159,6 +159,8 @@ struct pnp_resource {
void pnp_free_resource(struct pnp_resource *pnp_res);
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+ struct resource *res);
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
int flags);
struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 26b5d4b18dd7..72e822e17d47 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -58,7 +58,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
return 0
#define TEST_ALPHA(c) \
- if (!('@' <= (c) || (c) <= 'Z')) \
+ if (!('A' <= (c) && (c) <= 'Z')) \
return 0
static int __init ispnpidacpi(const char *id)
{
@@ -95,6 +95,9 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
return -ENODEV;
}
+ if (WARN_ON_ONCE(acpi_dev != dev->data))
+ dev->data = acpi_dev;
+
ret = pnpacpi_build_resource_template(dev, &buffer);
if (ret)
return ret;
@@ -242,6 +245,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
char *pnpid;
struct acpi_hardware_id *id;
+ /* Skip devices that are already bound */
+ if (device->physical_node_count)
+ return 0;
+
/*
* If a PnPacpi device is not present , the device
* driver should not be loaded.
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5be4a392a3ae..b8f4ea7b27fc 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -28,37 +28,6 @@
#include "../base.h"
#include "pnpacpi.h"
-#ifdef CONFIG_IA64
-#define valid_IRQ(i) (1)
-#else
-#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
-#endif
-
-/*
- * Allocated Resources
- */
-static int irq_flags(int triggering, int polarity, int shareable)
-{
- int flags;
-
- if (triggering == ACPI_LEVEL_SENSITIVE) {
- if (polarity == ACPI_ACTIVE_LOW)
- flags = IORESOURCE_IRQ_LOWLEVEL;
- else
- flags = IORESOURCE_IRQ_HIGHLEVEL;
- } else {
- if (polarity == ACPI_ACTIVE_LOW)
- flags = IORESOURCE_IRQ_LOWEDGE;
- else
- flags = IORESOURCE_IRQ_HIGHEDGE;
- }
-
- if (shareable == ACPI_SHARED)
- flags |= IORESOURCE_IRQ_SHAREABLE;
-
- return flags;
-}
-
static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
int *polarity, int *shareable)
{
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
*shareable = ACPI_EXCLUSIVE;
}
-static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
- u32 gsi, int triggering,
- int polarity, int shareable)
-{
- int irq, flags;
- int p, t;
-
- if (!valid_IRQ(gsi)) {
- pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
- return;
- }
-
- /*
- * in IO-APIC mode, use overrided attribute. Two reasons:
- * 1. BIOS bug in DSDT
- * 2. BIOS uses IO-APIC mode Interrupt Source Override
- */
- if (!acpi_get_override_irq(gsi, &t, &p)) {
- t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
- p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-
- if (triggering != t || polarity != p) {
- dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
- gsi, t ? "edge":"level", p ? "low":"high");
- triggering = t;
- polarity = p;
- }
- }
-
- flags = irq_flags(triggering, polarity, shareable);
- irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
- if (irq >= 0)
- pcibios_penalize_isa_irq(irq, 1);
- else
- flags |= IORESOURCE_DISABLED;
-
- pnp_add_irq_resource(dev, irq, flags);
-}
-
static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
int transfer)
{
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
return flags;
}
-static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
- u64 len, int io_decode,
- int window)
-{
- int flags = 0;
- u64 end = start + len - 1;
+/*
+ * Allocated Resources
+ */
- if (io_decode == ACPI_DECODE_16)
- flags |= IORESOURCE_IO_16BIT_ADDR;
- if (len == 0 || end >= 0x10003)
- flags |= IORESOURCE_DISABLED;
- if (window)
- flags |= IORESOURCE_WINDOW;
+static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
+{
+ if (!(r->flags & IORESOURCE_DISABLED))
+ pcibios_penalize_isa_irq(r->start, 1);
- pnp_add_io_resource(dev, start, end, flags);
+ pnp_add_resource(dev, r);
}
/*
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
}
}
-static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
- u64 start, u64 len,
- int write_protect, int window)
-{
- int flags = 0;
- u64 end = start + len - 1;
-
- if (len == 0)
- flags |= IORESOURCE_DISABLED;
- if (write_protect == ACPI_READ_WRITE_MEMORY)
- flags |= IORESOURCE_MEM_WRITEABLE;
- if (window)
- flags |= IORESOURCE_WINDOW;
-
- pnp_add_mem_resource(dev, start, end, flags);
-}
-
-static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
- u64 start, u64 len)
-{
- u64 end = start + len - 1;
-
- pnp_add_bus_resource(dev, start, end);
-}
-
-static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
- struct acpi_resource *res)
-{
- struct acpi_resource_address64 addr, *p = &addr;
- acpi_status status;
- int window;
- u64 len;
-
- status = acpi_resource_to_address64(res, p);
- if (!ACPI_SUCCESS(status)) {
- dev_warn(&dev->dev, "failed to convert resource type %d\n",
- res->type);
- return;
- }
-
- /* Windows apparently computes length rather than using _LEN */
- len = p->maximum - p->minimum + 1;
- window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
- if (p->resource_type == ACPI_MEMORY_RANGE)
- pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
- p->info.mem.write_protect, window);
- else if (p->resource_type == ACPI_IO_RANGE)
- pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
- p->granularity == 0xfff ? ACPI_DECODE_10 :
- ACPI_DECODE_16, window);
- else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
- pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
-static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
- struct acpi_resource *res)
-{
- struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
- int window;
- u64 len;
-
- /* Windows apparently computes length rather than using _LEN */
- len = p->maximum - p->minimum + 1;
- window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
- if (p->resource_type == ACPI_MEMORY_RANGE)
- pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
- p->info.mem.write_protect, window);
- else if (p->resource_type == ACPI_IO_RANGE)
- pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
- p->granularity == 0xfff ? ACPI_DECODE_10 :
- ACPI_DECODE_16, window);
- else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
- pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
void *data)
{
struct pnp_dev *dev = data;
- struct acpi_resource_irq *irq;
struct acpi_resource_dma *dma;
- struct acpi_resource_io *io;
- struct acpi_resource_fixed_io *fixed_io;
struct acpi_resource_vendor_typed *vendor_typed;
- struct acpi_resource_memory24 *memory24;
- struct acpi_resource_memory32 *memory32;
- struct acpi_resource_fixed_memory32 *fixed_memory32;
- struct acpi_resource_extended_irq *extended_irq;
+ struct resource r;
int i, flags;
- switch (res->type) {
- case ACPI_RESOURCE_TYPE_IRQ:
- /*
- * Per spec, only one interrupt per descriptor is allowed in
- * _CRS, but some firmware violates this, so parse them all.
- */
- irq = &res->data.irq;
- if (irq->interrupt_count == 0)
- pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
- else {
- for (i = 0; i < irq->interrupt_count; i++) {
- pnpacpi_parse_allocated_irqresource(dev,
- irq->interrupts[i],
- irq->triggering,
- irq->polarity,
- irq->sharable);
- }
+ if (acpi_dev_resource_memory(res, &r)
+ || acpi_dev_resource_io(res, &r)
+ || acpi_dev_resource_address_space(res, &r)
+ || acpi_dev_resource_ext_address_space(res, &r)) {
+ pnp_add_resource(dev, &r);
+ return AE_OK;
+ }
+ r.flags = 0;
+ if (acpi_dev_resource_interrupt(res, 0, &r)) {
+ pnpacpi_add_irqresource(dev, &r);
+ for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
+ pnpacpi_add_irqresource(dev, &r);
+
+ if (i > 1) {
/*
* The IRQ encoder puts a single interrupt in each
* descriptor, so if a _CRS descriptor has more than
* one interrupt, we won't be able to re-encode it.
*/
- if (pnp_can_write(dev) && irq->interrupt_count > 1) {
+ if (pnp_can_write(dev)) {
dev_warn(&dev->dev, "multiple interrupts in "
"_CRS descriptor; configuration can't "
"be changed\n");
dev->capabilities &= ~PNP_WRITE;
}
}
- break;
+ return AE_OK;
+ } else if (r.flags & IORESOURCE_DISABLED) {
+ pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
+ return AE_OK;
+ }
+ switch (res->type) {
case ACPI_RESOURCE_TYPE_DMA:
dma = &res->data.dma;
if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
pnp_add_dma_resource(dev, dma->channels[0], flags);
break;
- case ACPI_RESOURCE_TYPE_IO:
- io = &res->data.io;
- pnpacpi_parse_allocated_ioresource(dev,
- io->minimum,
- io->address_length,
- io->io_decode, 0);
- break;
-
case ACPI_RESOURCE_TYPE_START_DEPENDENT:
case ACPI_RESOURCE_TYPE_END_DEPENDENT:
break;
- case ACPI_RESOURCE_TYPE_FIXED_IO:
- fixed_io = &res->data.fixed_io;
- pnpacpi_parse_allocated_ioresource(dev,
- fixed_io->address,
- fixed_io->address_length,
- ACPI_DECODE_10, 0);
- break;
-
case ACPI_RESOURCE_TYPE_VENDOR:
vendor_typed = &res->data.vendor_typed;
pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
case ACPI_RESOURCE_TYPE_END_TAG:
break;
- case ACPI_RESOURCE_TYPE_MEMORY24:
- memory24 = &res->data.memory24;
- pnpacpi_parse_allocated_memresource(dev,
- memory24->minimum,
- memory24->address_length,
- memory24->write_protect, 0);
- break;
- case ACPI_RESOURCE_TYPE_MEMORY32:
- memory32 = &res->data.memory32;
- pnpacpi_parse_allocated_memresource(dev,
- memory32->minimum,
- memory32->address_length,
- memory32->write_protect, 0);
- break;
- case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
- fixed_memory32 = &res->data.fixed_memory32;
- pnpacpi_parse_allocated_memresource(dev,
- fixed_memory32->address,
- fixed_memory32->address_length,
- fixed_memory32->write_protect, 0);
- break;
- case ACPI_RESOURCE_TYPE_ADDRESS16:
- case ACPI_RESOURCE_TYPE_ADDRESS32:
- case ACPI_RESOURCE_TYPE_ADDRESS64:
- pnpacpi_parse_allocated_address_space(dev, res);
- break;
-
- case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
- pnpacpi_parse_allocated_ext_address_space(dev, res);
- break;
-
- case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
- extended_irq = &res->data.extended_irq;
-
- if (extended_irq->interrupt_count == 0)
- pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
- else {
- for (i = 0; i < extended_irq->interrupt_count; i++) {
- pnpacpi_parse_allocated_irqresource(dev,
- extended_irq->interrupts[i],
- extended_irq->triggering,
- extended_irq->polarity,
- extended_irq->sharable);
- }
-
- /*
- * The IRQ encoder puts a single interrupt in each
- * descriptor, so if a _CRS descriptor has more than
- * one interrupt, we won't be able to re-encode it.
- */
- if (pnp_can_write(dev) &&
- extended_irq->interrupt_count > 1) {
- dev_warn(&dev->dev, "multiple interrupts in "
- "_CRS descriptor; configuration can't "
- "be changed\n");
- dev->capabilities &= ~PNP_WRITE;
- }
- }
- break;
-
case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
break;
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
if (p->interrupts[i])
__set_bit(p->interrupts[i], map.bits);
- flags = irq_flags(p->triggering, p->polarity, p->sharable);
+ flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
}
}
- flags = irq_flags(p->triggering, p->polarity, p->sharable);
+ flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
pnp_register_irq_resource(dev, option_flags, &map, flags);
}
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 9d4222648640..5d66e5585f97 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -91,8 +91,6 @@ struct pnp_dev_node_info node_info;
*
*/
-#ifdef CONFIG_HOTPLUG
-
static struct completion unload_sem;
/*
@@ -199,8 +197,6 @@ static int pnp_dock_thread(void *unused)
complete_and_exit(&unload_sem, 0);
}
-#endif /* CONFIG_HOTPLUG */
-
static int pnpbios_get_resources(struct pnp_dev *dev)
{
u8 nodenum = dev->number;
@@ -573,21 +569,19 @@ fs_initcall(pnpbios_init);
static int __init pnpbios_thread_init(void)
{
+ struct task_struct *task;
#if defined(CONFIG_PPC)
if (check_legacy_ioport(PNPBIOS_BASE))
return 0;
#endif
if (pnpbios_disabled)
return 0;
-#ifdef CONFIG_HOTPLUG
- {
- struct task_struct *task;
- init_completion(&unload_sem);
- task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
- if (IS_ERR(task))
- return PTR_ERR(task);
- }
-#endif
+
+ init_completion(&unload_sem);
+ task = kthread_run(pnp_dock_thread, NULL, "kpnpbiosd");
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+
return 0;
}
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index b0ecacbe53b1..3e6db1c1dc29 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
return pnp_res;
}
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+ struct resource *res)
+{
+ struct pnp_resource *pnp_res;
+
+ pnp_res = pnp_new_resource(dev);
+ if (!pnp_res) {
+ dev_err(&dev->dev, "can't add resource %pR\n", res);
+ return NULL;
+ }
+
+ pnp_res->res = *res;
+ dev_dbg(&dev->dev, "%pR\n", res);
+ return pnp_res;
+}
+
struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
int flags)
{
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c
index beed5ecf75e1..8bc80b05c63c 100644
--- a/drivers/power/88pm860x_battery.c
+++ b/drivers/power/88pm860x_battery.c
@@ -901,7 +901,7 @@ static enum power_supply_property pm860x_batt_props[] = {
POWER_SUPPLY_PROP_TEMP,
};
-static __devinit int pm860x_battery_probe(struct platform_device *pdev)
+static int pm860x_battery_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_battery_info *info;
@@ -989,7 +989,7 @@ out:
return ret;
}
-static int __devexit pm860x_battery_remove(struct platform_device *pdev)
+static int pm860x_battery_remove(struct platform_device *pdev)
{
struct pm860x_battery_info *info = platform_get_drvdata(pdev);
@@ -1033,7 +1033,7 @@ static struct platform_driver pm860x_battery_driver = {
.pm = &pm860x_battery_pm_ops,
},
.probe = pm860x_battery_probe,
- .remove = __devexit_p(pm860x_battery_remove),
+ .remove = pm860x_battery_remove,
};
module_platform_driver(pm860x_battery_driver);
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c
index 2dbeb1460901..4b37a5af8deb 100644
--- a/drivers/power/88pm860x_charger.c
+++ b/drivers/power/88pm860x_charger.c
@@ -645,7 +645,7 @@ static struct pm860x_irq_desc {
{ "vchg", pm860x_vchg_handler },
};
-static __devinit int pm860x_charger_probe(struct platform_device *pdev)
+static int pm860x_charger_probe(struct platform_device *pdev)
{
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm860x_charger_info *info;
@@ -718,7 +718,7 @@ out:
return ret;
}
-static int __devexit pm860x_charger_remove(struct platform_device *pdev)
+static int pm860x_charger_remove(struct platform_device *pdev)
{
struct pm860x_charger_info *info = platform_get_drvdata(pdev);
int i;
@@ -738,7 +738,7 @@ static struct platform_driver pm860x_charger_driver = {
.owner = THIS_MODULE,
},
.probe = pm860x_charger_probe,
- .remove = __devexit_p(pm860x_charger_remove),
+ .remove = pm860x_charger_remove,
};
module_platform_driver(pm860x_charger_driver);
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c
index e3b6395b20dd..989b09950aff 100644
--- a/drivers/power/ab8500_btemp.c
+++ b/drivers/power/ab8500_btemp.c
@@ -938,7 +938,7 @@ static int ab8500_btemp_suspend(struct platform_device *pdev,
#define ab8500_btemp_resume NULL
#endif
-static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
+static int ab8500_btemp_remove(struct platform_device *pdev)
{
struct ab8500_btemp *di = platform_get_drvdata(pdev);
int i, irq;
@@ -960,7 +960,7 @@ static int __devexit ab8500_btemp_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit ab8500_btemp_probe(struct platform_device *pdev)
+static int ab8500_btemp_probe(struct platform_device *pdev)
{
int irq, i, ret = 0;
u8 val;
@@ -1101,7 +1101,7 @@ free_device_info:
static struct platform_driver ab8500_btemp_driver = {
.probe = ab8500_btemp_probe,
- .remove = __devexit_p(ab8500_btemp_remove),
+ .remove = ab8500_btemp_remove,
.suspend = ab8500_btemp_suspend,
.resume = ab8500_btemp_resume,
.driver = {
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 26ff759e2220..7ecb8abe20b5 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -2490,7 +2490,7 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
#define ab8500_charger_resume NULL
#endif
-static int __devexit ab8500_charger_remove(struct platform_device *pdev)
+static int ab8500_charger_remove(struct platform_device *pdev)
{
struct ab8500_charger *di = platform_get_drvdata(pdev);
int i, irq, ret;
@@ -2531,7 +2531,7 @@ static int __devexit ab8500_charger_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit ab8500_charger_probe(struct platform_device *pdev)
+static int ab8500_charger_probe(struct platform_device *pdev)
{
int irq, i, charger_status, ret = 0;
struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data;
@@ -2765,7 +2765,7 @@ free_device_info:
static struct platform_driver ab8500_charger_driver = {
.probe = ab8500_charger_probe,
- .remove = __devexit_p(ab8500_charger_remove),
+ .remove = ab8500_charger_remove,
.suspend = ab8500_charger_suspend,
.resume = ab8500_charger_resume,
.driver = {
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
index 2db8cc254399..331dc43ded4e 100644
--- a/drivers/power/ab8500_fg.c
+++ b/drivers/power/ab8500_fg.c
@@ -2411,7 +2411,7 @@ static int ab8500_fg_suspend(struct platform_device *pdev,
#define ab8500_fg_resume NULL
#endif
-static int __devexit ab8500_fg_remove(struct platform_device *pdev)
+static int ab8500_fg_remove(struct platform_device *pdev)
{
int ret = 0;
struct ab8500_fg *di = platform_get_drvdata(pdev);
@@ -2442,7 +2442,7 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
{"CCEOC", ab8500_fg_cc_data_end_handler},
};
-static int __devinit ab8500_fg_probe(struct platform_device *pdev)
+static int ab8500_fg_probe(struct platform_device *pdev)
{
int i, irq;
int ret = 0;
@@ -2614,7 +2614,7 @@ free_device_info:
static struct platform_driver ab8500_fg_driver = {
.probe = ab8500_fg_probe,
- .remove = __devexit_p(ab8500_fg_remove),
+ .remove = ab8500_fg_remove,
.suspend = ab8500_fg_suspend,
.resume = ab8500_fg_resume,
.driver = {
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 4d302803ffcc..19f254190790 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -1782,7 +1782,7 @@ static int abx500_chargalg_suspend(struct platform_device *pdev,
#define abx500_chargalg_resume NULL
#endif
-static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
+static int abx500_chargalg_remove(struct platform_device *pdev)
{
struct abx500_chargalg *di = platform_get_drvdata(pdev);
@@ -1800,7 +1800,7 @@ static int __devexit abx500_chargalg_remove(struct platform_device *pdev)
return 0;
}
-static int __devinit abx500_chargalg_probe(struct platform_device *pdev)
+static int abx500_chargalg_probe(struct platform_device *pdev)
{
struct abx500_bm_plat_data *plat_data;
int ret = 0;
@@ -1893,7 +1893,7 @@ free_device_info:
static struct platform_driver abx500_chargalg_driver = {
.probe = abx500_chargalg_probe,
- .remove = __devexit_p(abx500_chargalg_remove),
+ .remove = abx500_chargalg_remove,
.suspend = abx500_chargalg_suspend,
.resume = abx500_chargalg_resume,
.driver = {
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
index 24768a27e1d8..d0fed2c5cf2c 100644
--- a/drivers/power/avs/smartreflex.c
+++ b/drivers/power/avs/smartreflex.c
@@ -1026,7 +1026,7 @@ err_free_devinfo:
return ret;
}
-static int __devexit omap_sr_remove(struct platform_device *pdev)
+static int omap_sr_remove(struct platform_device *pdev)
{
struct omap_sr_data *pdata = pdev->dev.platform_data;
struct omap_sr *sr_info;
@@ -1059,7 +1059,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
return 0;
}
-static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+static void omap_sr_shutdown(struct platform_device *pdev)
{
struct omap_sr_data *pdata = pdev->dev.platform_data;
struct omap_sr *sr_info;
@@ -1083,8 +1083,8 @@ static void __devexit omap_sr_shutdown(struct platform_device *pdev)
}
static struct platform_driver smartreflex_driver = {
- .remove = __devexit_p(omap_sr_remove),
- .shutdown = __devexit_p(omap_sr_shutdown),
+ .remove = omap_sr_remove,
+ .shutdown = omap_sr_shutdown,
.driver = {
.name = "smartreflex",
},
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 5860d4dfbe9c..e0edaf7de54b 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -926,7 +926,7 @@ static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
return pdata->read(dev, reg);
}
-static int __devinit bq27000_battery_probe(struct platform_device *pdev)
+static int bq27000_battery_probe(struct platform_device *pdev)
{
struct bq27x00_device_info *di;
struct bq27000_platform_data *pdata = pdev->dev.platform_data;
@@ -969,7 +969,7 @@ err_free:
return ret;
}
-static int __devexit bq27000_battery_remove(struct platform_device *pdev)
+static int bq27000_battery_remove(struct platform_device *pdev)
{
struct bq27x00_device_info *di = platform_get_drvdata(pdev);
@@ -983,7 +983,7 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev)
static struct platform_driver bq27000_battery_driver = {
.probe = bq27000_battery_probe,
- .remove = __devexit_p(bq27000_battery_remove),
+ .remove = bq27000_battery_remove,
.driver = {
.name = "bq27000-battery",
.owner = THIS_MODULE,
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 8a0aca6364c7..adb3a4b59cb3 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1655,7 +1655,7 @@ err_alloc:
return ret;
}
-static int __devexit charger_manager_remove(struct platform_device *pdev)
+static int charger_manager_remove(struct platform_device *pdev)
{
struct charger_manager *cm = platform_get_drvdata(pdev);
struct charger_desc *desc = cm->desc;
@@ -1812,7 +1812,7 @@ static struct platform_driver charger_manager_driver = {
.pm = &charger_manager_pm,
},
.probe = charger_manager_probe,
- .remove = __devexit_p(charger_manager_remove),
+ .remove = charger_manager_remove,
.id_table = charger_manager_id,
};
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
index b19bfe400f8c..c58d0e31bdef 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -305,7 +305,7 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
#define collie_bat_resume NULL
#endif
-static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
+static int collie_bat_probe(struct ucb1x00_dev *dev)
{
int ret;
@@ -349,7 +349,7 @@ err_psy_reg_main:
return ret;
}
-static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
+static void collie_bat_remove(struct ucb1x00_dev *dev)
{
free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
@@ -367,7 +367,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
static struct ucb1x00_driver collie_bat_driver = {
.add = collie_bat_probe,
- .remove = __devexit_p(collie_bat_remove),
+ .remove = collie_bat_remove,
.suspend = collie_bat_suspend,
.resume = collie_bat_resume,
};
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
index d9d034d7496f..bb0df8917adc 100644
--- a/drivers/power/da9052-battery.c
+++ b/drivers/power/da9052-battery.c
@@ -576,7 +576,7 @@ static const char *const da9052_bat_irqs[] = {
"CHG END",
};
-static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
+static s32 da9052_bat_probe(struct platform_device *pdev)
{
struct da9052_pdata *pdata;
struct da9052_battery *bat;
@@ -630,7 +630,7 @@ err:
kfree(bat);
return ret;
}
-static int __devexit da9052_bat_remove(struct platform_device *pdev)
+static int da9052_bat_remove(struct platform_device *pdev)
{
int i;
int irq;
@@ -648,7 +648,7 @@ static int __devexit da9052_bat_remove(struct platform_device *pdev)
static struct platform_driver da9052_bat_driver = {
.probe = da9052_bat_probe,
- .remove = __devexit_p(da9052_bat_remove),
+ .remove = da9052_bat_remove,
.driver = {
.name = "da9052-bat",
.owner = THIS_MODULE,
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 74fad941c56c..8b6c4539e7f4 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -755,7 +755,7 @@ static const struct attribute_group ds2780_attr_group = {
.attrs = ds2780_attributes,
};
-static int __devinit ds2780_battery_probe(struct platform_device *pdev)
+static int ds2780_battery_probe(struct platform_device *pdev)
{
int ret = 0;
struct ds2780_device_info *dev_info;
@@ -819,7 +819,7 @@ fail:
return ret;
}
-static int __devexit ds2780_battery_remove(struct platform_device *pdev)
+static int ds2780_battery_remove(struct platform_device *pdev)
{
struct ds2780_device_info *dev_info = platform_get_drvdata(pdev);
@@ -837,7 +837,7 @@ static struct platform_driver ds2780_battery_driver = {
.name = "ds2780-battery",
},
.probe = ds2780_battery_probe,
- .remove = __devexit_p(ds2780_battery_remove),
+ .remove = ds2780_battery_remove,
};
module_platform_driver(ds2780_battery_driver);
diff --git a/drivers/power/ds2781_battery.c b/drivers/power/ds2781_battery.c
index 22b3c8c93552..0a5acc6fc6f0 100644
--- a/drivers/power/ds2781_battery.c
+++ b/drivers/power/ds2781_battery.c
@@ -750,7 +750,7 @@ static const struct attribute_group ds2781_attr_group = {
.attrs = ds2781_attributes,
};
-static int __devinit ds2781_battery_probe(struct platform_device *pdev)
+static int ds2781_battery_probe(struct platform_device *pdev)
{
int ret = 0;
struct ds2781_device_info *dev_info;
@@ -810,7 +810,7 @@ fail:
return ret;
}
-static int __devexit ds2781_battery_remove(struct platform_device *pdev)
+static int ds2781_battery_remove(struct platform_device *pdev)
{
struct ds2781_device_info *dev_info = platform_get_drvdata(pdev);
@@ -827,7 +827,7 @@ static struct platform_driver ds2781_battery_driver = {
.name = "ds2781-battery",
},
.probe = ds2781_battery_probe,
- .remove = __devexit_p(ds2781_battery_remove),
+ .remove = ds2781_battery_remove,
};
module_platform_driver(ds2781_battery_driver);
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
index 9bdf44470396..e902b088d52c 100644
--- a/drivers/power/generic-adc-battery.c
+++ b/drivers/power/generic-adc-battery.c
@@ -236,7 +236,7 @@ static irqreturn_t gab_charged(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit gab_probe(struct platform_device *pdev)
+static int gab_probe(struct platform_device *pdev)
{
struct gab *adc_bat;
struct power_supply *psy;
@@ -351,7 +351,7 @@ first_mem_fail:
return ret;
}
-static int __devexit gab_remove(struct platform_device *pdev)
+static int gab_remove(struct platform_device *pdev)
{
int chan;
struct gab *adc_bat = platform_get_drvdata(pdev);
@@ -413,7 +413,7 @@ static struct platform_driver gab_driver = {
.pm = GAB_PM_OPS
},
.probe = gab_probe,
- .remove = __devexit_p(gab_remove),
+ .remove = gab_remove,
};
module_platform_driver(gab_driver);
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index cb2aa3195687..e3e40a9f3af2 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -68,7 +68,7 @@ static enum power_supply_property gpio_charger_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
};
-static int __devinit gpio_charger_probe(struct platform_device *pdev)
+static int gpio_charger_probe(struct platform_device *pdev)
{
const struct gpio_charger_platform_data *pdata = pdev->dev.platform_data;
struct gpio_charger *gpio_charger;
@@ -144,7 +144,7 @@ err_free:
return ret;
}
-static int __devexit gpio_charger_remove(struct platform_device *pdev)
+static int gpio_charger_remove(struct platform_device *pdev)
{
struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
@@ -177,7 +177,7 @@ static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
static struct platform_driver gpio_charger_driver = {
.probe = gpio_charger_probe,
- .remove = __devexit_p(gpio_charger_remove),
+ .remove = gpio_charger_remove,
.driver = {
.name = "gpio-charger",
.owner = THIS_MODULE,
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index d09649706bd3..18d136b443ee 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -649,7 +649,7 @@ static void pmic_battery_handle_intrpt(struct work_struct *work)
* PMIC battery initializes its internal data structue and other
* infrastructure components for it to work as expected.
*/
-static __devinit int probe(int irq, struct device *dev)
+static int probe(int irq, struct device *dev)
{
int retval = 0;
struct pmic_power_module_info *pbi;
@@ -739,7 +739,7 @@ wqueue_failed:
return retval;
}
-static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
+static int platform_pmic_battery_probe(struct platform_device *pdev)
{
return probe(pdev->id, &pdev->dev);
}
@@ -754,7 +754,7 @@ static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
* pmic_battery_probe.
*/
-static int __devexit platform_pmic_battery_remove(struct platform_device *pdev)
+static int platform_pmic_battery_remove(struct platform_device *pdev)
{
struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev);
@@ -776,7 +776,7 @@ static struct platform_driver platform_pmic_battery_driver = {
.owner = THIS_MODULE,
},
.probe = platform_pmic_battery_probe,
- .remove = __devexit_p(platform_pmic_battery_remove),
+ .remove = platform_pmic_battery_remove,
};
module_platform_driver(platform_pmic_battery_driver);
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 122911978da2..176ad59d99f5 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -406,7 +406,7 @@ static inline int isp1704_test_ulpi(struct isp1704_charger *isp)
return -ENODEV;
}
-static int __devinit isp1704_charger_probe(struct platform_device *pdev)
+static int isp1704_charger_probe(struct platform_device *pdev)
{
struct isp1704_charger *isp;
int ret = -ENODEV;
@@ -484,7 +484,7 @@ fail0:
return ret;
}
-static int __devexit isp1704_charger_remove(struct platform_device *pdev)
+static int isp1704_charger_remove(struct platform_device *pdev)
{
struct isp1704_charger *isp = platform_get_drvdata(pdev);
@@ -502,7 +502,7 @@ static struct platform_driver isp1704_charger_driver = {
.name = "isp1704_charger",
},
.probe = isp1704_charger_probe,
- .remove = __devexit_p(isp1704_charger_remove),
+ .remove = isp1704_charger_remove,
};
module_platform_driver(isp1704_charger_driver);
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index ffbed5e5b945..74ac69e0687f 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -238,7 +238,7 @@ static void jz_battery_work(struct work_struct *work)
schedule_delayed_work(&jz_battery->work, interval);
}
-static int __devinit jz_battery_probe(struct platform_device *pdev)
+static int jz_battery_probe(struct platform_device *pdev)
{
int ret = 0;
struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data;
@@ -376,7 +376,7 @@ err_free:
return ret;
}
-static int __devexit jz_battery_remove(struct platform_device *pdev)
+static int jz_battery_remove(struct platform_device *pdev)
{
struct jz_battery *jz_battery = platform_get_drvdata(pdev);
@@ -431,7 +431,7 @@ static const struct dev_pm_ops jz_battery_pm_ops = {
static struct platform_driver jz_battery_driver = {
.probe = jz_battery_probe,
- .remove = __devexit_p(jz_battery_remove),
+ .remove = jz_battery_remove,
.driver = {
.name = "jz4740-battery",
.owner = THIS_MODULE,
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
index c628224b7f58..4ee71a90e248 100644
--- a/drivers/power/lp8727_charger.c
+++ b/drivers/power/lp8727_charger.c
@@ -522,7 +522,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
return 0;
}
-static int __devexit lp8727_remove(struct i2c_client *cl)
+static int lp8727_remove(struct i2c_client *cl)
{
struct lp8727_chg *pchg = i2c_get_clientdata(cl);
@@ -542,7 +542,7 @@ static struct i2c_driver lp8727_driver = {
.name = "lp8727",
},
.probe = lp8727_probe,
- .remove = __devexit_p(lp8727_remove),
+ .remove = lp8727_remove,
.id_table = lp8727_ids,
};
module_i2c_driver(lp8727_driver);
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c
index e852d12cd077..a1c51ac117fd 100644
--- a/drivers/power/lp8788-charger.c
+++ b/drivers/power/lp8788-charger.c
@@ -729,7 +729,7 @@ static const struct attribute_group lp8788_attr_group = {
.attrs = lp8788_charger_attr,
};
-static __devinit int lp8788_charger_probe(struct platform_device *pdev)
+static int lp8788_charger_probe(struct platform_device *pdev)
{
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
struct lp8788_charger *pchg;
@@ -766,7 +766,7 @@ static __devinit int lp8788_charger_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lp8788_charger_remove(struct platform_device *pdev)
+static int lp8788_charger_remove(struct platform_device *pdev)
{
struct lp8788_charger *pchg = platform_get_drvdata(pdev);
@@ -781,7 +781,7 @@ static int __devexit lp8788_charger_remove(struct platform_device *pdev)
static struct platform_driver lp8788_charger_driver = {
.probe = lp8788_charger_probe,
- .remove = __devexit_p(lp8788_charger_remove),
+ .remove = lp8788_charger_remove,
.driver = {
.name = LP8788_DEV_CHARGER,
.owner = THIS_MODULE,
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 58e67830143c..22cfe9cc4727 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -197,7 +197,7 @@ static enum power_supply_property max17040_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
};
-static int __devinit max17040_probe(struct i2c_client *client,
+static int max17040_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -238,7 +238,7 @@ static int __devinit max17040_probe(struct i2c_client *client,
return 0;
}
-static int __devexit max17040_remove(struct i2c_client *client)
+static int max17040_remove(struct i2c_client *client)
{
struct max17040_chip *chip = i2c_get_clientdata(client);
@@ -285,7 +285,7 @@ static struct i2c_driver max17040_i2c_driver = {
.name = "max17040",
},
.probe = max17040_probe,
- .remove = __devexit_p(max17040_remove),
+ .remove = max17040_remove,
.suspend = max17040_suspend,
.resume = max17040_resume,
.id_table = max17040_id,
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 74abc6c755b4..5ffe46916f0b 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -681,7 +681,7 @@ max17042_get_pdata(struct device *dev)
}
#endif
-static int __devinit max17042_probe(struct i2c_client *client,
+static int max17042_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -775,7 +775,7 @@ static int __devinit max17042_probe(struct i2c_client *client,
return 0;
}
-static int __devexit max17042_remove(struct i2c_client *client)
+static int max17042_remove(struct i2c_client *client)
{
struct max17042_chip *chip = i2c_get_clientdata(client);
@@ -851,7 +851,7 @@ static struct i2c_driver max17042_i2c_driver = {
.pm = MAX17042_PM_OPS,
},
.probe = max17042_probe,
- .remove = __devexit_p(max17042_remove),
+ .remove = max17042_remove,
.id_table = max17042_id,
};
module_i2c_driver(max17042_i2c_driver);
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 3e23f43e98af..14e2b96d93b0 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -179,7 +179,7 @@ static irqreturn_t max8903_fault(int irq, void *_data)
return IRQ_HANDLED;
}
-static __devinit int max8903_probe(struct platform_device *pdev)
+static int max8903_probe(struct platform_device *pdev)
{
struct max8903_data *data;
struct device *dev = &pdev->dev;
@@ -345,7 +345,7 @@ err:
return ret;
}
-static __devexit int max8903_remove(struct platform_device *pdev)
+static int max8903_remove(struct platform_device *pdev)
{
struct max8903_data *data = platform_get_drvdata(pdev);
@@ -367,7 +367,7 @@ static __devexit int max8903_remove(struct platform_device *pdev)
static struct platform_driver max8903_driver = {
.probe = max8903_probe,
- .remove = __devexit_p(max8903_remove),
+ .remove = max8903_remove,
.driver = {
.name = "max8903-charger",
.owner = THIS_MODULE,
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index daa333bd7ebb..1a075f1f1b67 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -356,7 +356,7 @@ do { \
_irq, ret); \
} while (0)
-static __devinit int max8925_init_charger(struct max8925_chip *chip,
+static int max8925_init_charger(struct max8925_chip *chip,
struct max8925_power_info *info)
{
int ret;
@@ -414,7 +414,7 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
return 0;
}
-static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
+static int max8925_deinit_charger(struct max8925_power_info *info)
{
struct max8925_chip *chip = info->chip;
int irq;
@@ -426,7 +426,7 @@ static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
return 0;
}
-static __devinit int max8925_power_probe(struct platform_device *pdev)
+static int max8925_power_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_power_pdata *pdata = NULL;
@@ -501,7 +501,7 @@ out:
return ret;
}
-static __devexit int max8925_power_remove(struct platform_device *pdev)
+static int max8925_power_remove(struct platform_device *pdev)
{
struct max8925_power_info *info = platform_get_drvdata(pdev);
@@ -517,7 +517,7 @@ static __devexit int max8925_power_remove(struct platform_device *pdev)
static struct platform_driver max8925_power_driver = {
.probe = max8925_power_probe,
- .remove = __devexit_p(max8925_power_remove),
+ .remove = max8925_power_remove,
.driver = {
.name = "max8925-power",
},
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index 6e88c5d026b9..e757885b620c 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -86,7 +86,7 @@ static int max8997_battery_get_property(struct power_supply *psy,
return 0;
}
-static __devinit int max8997_battery_probe(struct platform_device *pdev)
+static int max8997_battery_probe(struct platform_device *pdev)
{
int ret = 0;
struct charger_data *charger;
@@ -167,7 +167,7 @@ err:
return ret;
}
-static int __devexit max8997_battery_remove(struct platform_device *pdev)
+static int max8997_battery_remove(struct platform_device *pdev)
{
struct charger_data *charger = platform_get_drvdata(pdev);
@@ -187,7 +187,7 @@ static struct platform_driver max8997_battery_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_battery_probe,
- .remove = __devexit_p(max8997_battery_remove),
+ .remove = max8997_battery_remove,
.id_table = max8997_battery_id,
};
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 6dc01c255592..bf677e3daec9 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -75,7 +75,7 @@ static int max8998_battery_get_property(struct power_supply *psy,
return 0;
}
-static __devinit int max8998_battery_probe(struct platform_device *pdev)
+static int max8998_battery_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);
@@ -178,7 +178,7 @@ err:
return ret;
}
-static int __devexit max8998_battery_remove(struct platform_device *pdev)
+static int max8998_battery_remove(struct platform_device *pdev)
{
struct max8998_battery_data *max8998 = platform_get_drvdata(pdev);
@@ -199,7 +199,7 @@ static struct platform_driver max8998_battery_driver = {
.owner = THIS_MODULE,
},
.probe = max8998_battery_probe,
- .remove = __devexit_p(max8998_battery_remove),
+ .remove = max8998_battery_remove,
.id_table = max8998_battery_id,
};
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index a89a41acf9c5..298c47d111b4 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -598,7 +598,7 @@ static int olpc_battery_suspend(struct platform_device *pdev,
return 0;
}
-static int __devinit olpc_battery_probe(struct platform_device *pdev)
+static int olpc_battery_probe(struct platform_device *pdev)
{
int ret;
uint8_t status;
@@ -659,7 +659,7 @@ battery_failed:
return ret;
}
-static int __devexit olpc_battery_remove(struct platform_device *pdev)
+static int olpc_battery_remove(struct platform_device *pdev)
{
device_remove_file(olpc_bat.dev, &olpc_bat_error);
device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
@@ -681,7 +681,7 @@ static struct platform_driver olpc_battery_driver = {
.of_match_table = olpc_battery_ids,
},
.probe = olpc_battery_probe,
- .remove = __devexit_p(olpc_battery_remove),
+ .remove = olpc_battery_remove,
.suspend = olpc_battery_suspend,
};
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 3d1e9efb6f53..c2122a7ad065 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -366,7 +366,7 @@ static const u8 mbc_irq_handlers[] = {
PCF50633_IRQ_LOWBAT,
};
-static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
+static int pcf50633_mbc_probe(struct platform_device *pdev)
{
struct pcf50633_mbc *mbc;
int ret;
@@ -447,7 +447,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
+static int pcf50633_mbc_remove(struct platform_device *pdev)
{
struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
int i;
@@ -471,7 +471,7 @@ static struct platform_driver pcf50633_mbc_driver = {
.name = "pcf50633-mbc",
},
.probe = pcf50633_mbc_probe,
- .remove = __devexit_p(pcf50633_mbc_remove),
+ .remove = pcf50633_mbc_remove,
};
module_platform_driver(pcf50633_mbc_driver);
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index 8b804a566756..d2ca989dcbdc 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -286,7 +286,7 @@ static irqreturn_t s3c_adc_bat_charged(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit s3c_adc_bat_probe(struct platform_device *pdev)
+static int s3c_adc_bat_probe(struct platform_device *pdev)
{
struct s3c_adc_client *client;
struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c
index 4146596d254b..3960f0b2afe9 100644
--- a/drivers/power/sbs-battery.c
+++ b/drivers/power/sbs-battery.c
@@ -675,7 +675,7 @@ static struct sbs_platform_data *sbs_of_populate_pdata(
}
#endif
-static int __devinit sbs_probe(struct i2c_client *client,
+static int sbs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct sbs_info *chip;
@@ -800,7 +800,7 @@ exit_free_name:
return rc;
}
-static int __devexit sbs_remove(struct i2c_client *client)
+static int sbs_remove(struct i2c_client *client)
{
struct sbs_info *chip = i2c_get_clientdata(client);
@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
static struct i2c_driver sbs_battery_driver = {
.probe = sbs_probe,
- .remove = __devexit_p(sbs_remove),
+ .remove = sbs_remove,
.suspend = sbs_suspend,
.resume = sbs_resume,
.id_table = sbs_id,
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c
index a9707c11fbed..acf84e80fe98 100644
--- a/drivers/power/smb347-charger.c
+++ b/drivers/power/smb347-charger.c
@@ -1313,7 +1313,7 @@ static struct i2c_driver smb347_driver = {
.name = "smb347",
},
.probe = smb347_probe,
- .remove = __devexit_p(smb347_remove),
+ .remove = smb347_remove,
.id_table = smb347_id,
};
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index 51199b5ce221..0224de50c540 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -342,7 +342,7 @@ static int tosa_bat_resume(struct platform_device *dev)
#define tosa_bat_resume NULL
#endif
-static int __devinit tosa_bat_probe(struct platform_device *dev)
+static int tosa_bat_probe(struct platform_device *dev)
{
int ret;
@@ -409,7 +409,7 @@ err_psy_reg_main:
return ret;
}
-static int __devexit tosa_bat_remove(struct platform_device *dev)
+static int tosa_bat_remove(struct platform_device *dev)
{
free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
@@ -433,7 +433,7 @@ static struct platform_driver tosa_bat_driver = {
.driver.name = "wm97xx-battery",
.driver.owner = THIS_MODULE,
.probe = tosa_bat_probe,
- .remove = __devexit_p(tosa_bat_remove),
+ .remove = tosa_bat_remove,
.suspend = tosa_bat_suspend,
.resume = tosa_bat_resume,
};
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index 6243e6975126..d9cc169f1424 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -161,7 +161,7 @@ static enum power_supply_property wm831x_backup_props[] = {
* Initialisation
*********************************************************************/
-static __devinit int wm831x_backup_probe(struct platform_device *pdev)
+static int wm831x_backup_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
@@ -207,7 +207,7 @@ err_kmalloc:
return ret;
}
-static __devexit int wm831x_backup_remove(struct platform_device *pdev)
+static int wm831x_backup_remove(struct platform_device *pdev)
{
struct wm831x_backup *devdata = platform_get_drvdata(pdev);
@@ -220,7 +220,7 @@ static __devexit int wm831x_backup_remove(struct platform_device *pdev)
static struct platform_driver wm831x_backup_driver = {
.probe = wm831x_backup_probe,
- .remove = __devexit_p(wm831x_backup_remove),
+ .remove = wm831x_backup_remove,
.driver = {
.name = "wm831x-backup",
},
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index fc1ad9551182..3bed2f55cf7d 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -489,7 +489,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static __devinit int wm831x_power_probe(struct platform_device *pdev)
+static int wm831x_power_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
@@ -625,7 +625,7 @@ err_kmalloc:
return ret;
}
-static __devexit int wm831x_power_remove(struct platform_device *pdev)
+static int wm831x_power_remove(struct platform_device *pdev)
{
struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
struct wm831x *wm831x = wm831x_power->wm831x;
@@ -654,7 +654,7 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
static struct platform_driver wm831x_power_driver = {
.probe = wm831x_power_probe,
- .remove = __devexit_p(wm831x_power_remove),
+ .remove = wm831x_power_remove,
.driver = {
.name = "wm831x-power",
},
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index fae04d384657..b3607e2906d2 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -442,7 +442,7 @@ static void free_charger_irq(struct wm8350 *wm8350)
wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
}
-static __devinit int wm8350_power_probe(struct platform_device *pdev)
+static int wm8350_power_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
struct wm8350_power *power = &wm8350->power;
@@ -501,7 +501,7 @@ battery_failed:
return ret;
}
-static __devexit int wm8350_power_remove(struct platform_device *pdev)
+static int wm8350_power_remove(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
struct wm8350_power *power = &wm8350->power;
@@ -516,7 +516,7 @@ static __devexit int wm8350_power_remove(struct platform_device *pdev)
static struct platform_driver wm8350_power_driver = {
.probe = wm8350_power_probe,
- .remove = __devexit_p(wm8350_power_remove),
+ .remove = wm8350_power_remove,
.driver = {
.name = "wm8350-power",
},
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index e128a813dc24..58f7348e6c22 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -162,7 +162,7 @@ static const struct dev_pm_ops wm97xx_bat_pm_ops = {
};
#endif
-static int __devinit wm97xx_bat_probe(struct platform_device *dev)
+static int wm97xx_bat_probe(struct platform_device *dev)
{
int ret = 0;
int props = 1; /* POWER_SUPPLY_PROP_PRESENT */
@@ -263,7 +263,7 @@ err:
return ret;
}
-static int __devexit wm97xx_bat_remove(struct platform_device *dev)
+static int wm97xx_bat_remove(struct platform_device *dev)
{
struct wm97xx_pdata *wmdata = dev->dev.platform_data;
struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
@@ -287,7 +287,7 @@ static struct platform_driver wm97xx_bat_driver = {
#endif
},
.probe = wm97xx_bat_probe,
- .remove = __devexit_p(wm97xx_bat_remove),
+ .remove = wm97xx_bat_remove,
};
module_platform_driver(wm97xx_bat_driver);
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index 5757d0d6782f..814d2e31f0c9 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -180,7 +180,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
return 0;
}
-static int __devinit z2_batt_probe(struct i2c_client *client,
+static int z2_batt_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
@@ -251,7 +251,7 @@ err:
return ret;
}
-static int __devexit z2_batt_remove(struct i2c_client *client)
+static int z2_batt_remove(struct i2c_client *client)
{
struct z2_charger *charger = i2c_get_clientdata(client);
struct z2_battery_info *info = charger->info;
@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
.pm = Z2_BATTERY_PM_OPS
},
.probe = z2_batt_probe,
- .remove = __devexit_p(z2_batt_remove),
+ .remove = z2_batt_remove,
.id_table = z2_batt_id,
};
module_i2c_driver(z2_batt_driver);
diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c
index e624e4dd2abb..1367655eee39 100644
--- a/drivers/ptp/ptp_pch.c
+++ b/drivers/ptp/ptp_pch.c
@@ -557,7 +557,7 @@ static s32 pch_resume(struct pci_dev *pdev)
#define pch_resume NULL
#endif
-static void __devexit pch_remove(struct pci_dev *pdev)
+static void pch_remove(struct pci_dev *pdev)
{
struct pch_dev *chip = pci_get_drvdata(pdev);
@@ -581,7 +581,7 @@ static void __devexit pch_remove(struct pci_dev *pdev)
dev_info(&pdev->dev, "complete\n");
}
-static s32 __devinit
+static s32
pch_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
s32 ret;
diff --git a/drivers/pwm/pwm-ab8500.c b/drivers/pwm/pwm-ab8500.c
index cfb72ca873d1..4248d0418273 100644
--- a/drivers/pwm/pwm-ab8500.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -90,7 +90,7 @@ static const struct pwm_ops ab8500_pwm_ops = {
.disable = ab8500_pwm_disable,
};
-static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
+static int ab8500_pwm_probe(struct platform_device *pdev)
{
struct ab8500_pwm_chip *ab8500;
int err;
@@ -122,7 +122,7 @@ static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
+static int ab8500_pwm_remove(struct platform_device *pdev)
{
struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
int err;
@@ -143,7 +143,7 @@ static struct platform_driver ab8500_pwm_driver = {
.owner = THIS_MODULE,
},
.probe = ab8500_pwm_probe,
- .remove = __devexit_p(ab8500_pwm_remove),
+ .remove = ab8500_pwm_remove,
};
module_platform_driver(ab8500_pwm_driver);
diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
index 5da8e185e838..7631ef194de7 100644
--- a/drivers/pwm/pwm-bfin.c
+++ b/drivers/pwm/pwm-bfin.c
@@ -139,7 +139,7 @@ static int bfin_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit bfin_pwm_remove(struct platform_device *pdev)
+static int bfin_pwm_remove(struct platform_device *pdev)
{
struct bfin_pwm_chip *pwm = platform_get_drvdata(pdev);
@@ -151,7 +151,7 @@ static struct platform_driver bfin_pwm_driver = {
.name = "bfin-pwm",
},
.probe = bfin_pwm_probe,
- .remove = __devexit_p(bfin_pwm_remove),
+ .remove = bfin_pwm_remove,
};
module_platform_driver(bfin_pwm_driver);
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 8a5d3ae2946a..8f26e9fcea97 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -231,7 +231,7 @@ static const struct of_device_id imx_pwm_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
-static int __devinit imx_pwm_probe(struct platform_device *pdev)
+static int imx_pwm_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(imx_pwm_dt_ids, &pdev->dev);
@@ -290,7 +290,7 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit imx_pwm_remove(struct platform_device *pdev)
+static int imx_pwm_remove(struct platform_device *pdev)
{
struct imx_chip *imx;
@@ -307,7 +307,7 @@ static struct platform_driver imx_pwm_driver = {
.of_match_table = of_match_ptr(imx_pwm_dt_ids),
},
.probe = imx_pwm_probe,
- .remove = __devexit_p(imx_pwm_remove),
+ .remove = imx_pwm_remove,
};
module_platform_driver(imx_pwm_driver);
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index 10250fcefb98..0a2ede3c3932 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -162,7 +162,7 @@ static const struct pwm_ops jz4740_pwm_ops = {
.owner = THIS_MODULE,
};
-static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
+static int jz4740_pwm_probe(struct platform_device *pdev)
{
struct jz4740_pwm_chip *jz4740;
int ret;
@@ -191,7 +191,7 @@ static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
+static int jz4740_pwm_remove(struct platform_device *pdev)
{
struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
int ret;
@@ -211,7 +211,7 @@ static struct platform_driver jz4740_pwm_driver = {
.owner = THIS_MODULE,
},
.probe = jz4740_pwm_probe,
- .remove = __devexit_p(jz4740_pwm_remove),
+ .remove = jz4740_pwm_remove,
};
module_platform_driver(jz4740_pwm_driver);
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index adb87f0c1633..015a82235620 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -118,7 +118,7 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit lpc32xx_pwm_remove(struct platform_device *pdev)
+static int lpc32xx_pwm_remove(struct platform_device *pdev)
{
struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev);
@@ -138,7 +138,7 @@ static struct platform_driver lpc32xx_pwm_driver = {
.of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids),
},
.probe = lpc32xx_pwm_probe,
- .remove = __devexit_p(lpc32xx_pwm_remove),
+ .remove = lpc32xx_pwm_remove,
};
module_platform_driver(lpc32xx_pwm_driver);
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index e5852646f082..7ec345f01831 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -174,7 +174,7 @@ static int mxs_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mxs_pwm_remove(struct platform_device *pdev)
+static int mxs_pwm_remove(struct platform_device *pdev)
{
struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev);
@@ -193,7 +193,7 @@ static struct platform_driver mxs_pwm_driver = {
.of_match_table = of_match_ptr(mxs_pwm_dt_ids),
},
.probe = mxs_pwm_probe,
- .remove = __devexit_p(mxs_pwm_remove),
+ .remove = mxs_pwm_remove,
};
module_platform_driver(mxs_pwm_driver);
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
index 2a93f37c46ad..b882f6032fee 100644
--- a/drivers/pwm/pwm-puv3.c
+++ b/drivers/pwm/pwm-puv3.c
@@ -101,7 +101,7 @@ static const struct pwm_ops puv3_pwm_ops = {
.owner = THIS_MODULE,
};
-static int __devinit pwm_probe(struct platform_device *pdev)
+static int pwm_probe(struct platform_device *pdev)
{
struct puv3_pwm_chip *puv3;
struct resource *r;
@@ -142,7 +142,7 @@ static int __devinit pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pwm_remove(struct platform_device *pdev)
+static int pwm_remove(struct platform_device *pdev)
{
struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
@@ -154,7 +154,7 @@ static struct platform_driver puv3_pwm_driver = {
.name = "PKUnity-v3-PWM",
},
.probe = pwm_probe,
- .remove = __devexit_p(pwm_remove),
+ .remove = pwm_remove,
};
module_platform_driver(puv3_pwm_driver);
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index 260c3a88564d..f32fc4e66e0c 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -135,7 +135,7 @@ static struct pwm_ops pxa_pwm_ops = {
.owner = THIS_MODULE,
};
-static int __devinit pwm_probe(struct platform_device *pdev)
+static int pwm_probe(struct platform_device *pdev)
{
const struct platform_device_id *id = platform_get_device_id(pdev);
struct pxa_pwm_chip *pwm;
@@ -179,7 +179,7 @@ static int __devinit pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pwm_remove(struct platform_device *pdev)
+static int pwm_remove(struct platform_device *pdev)
{
struct pxa_pwm_chip *chip;
@@ -196,7 +196,7 @@ static struct platform_driver pwm_driver = {
.owner = THIS_MODULE,
},
.probe = pwm_probe,
- .remove = __devexit_p(pwm_remove),
+ .remove = pwm_remove,
.id_table = pwm_id_table,
};
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index 023a3bee76e7..e9b15d099c03 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -273,7 +273,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit s3c_pwm_remove(struct platform_device *pdev)
+static int s3c_pwm_remove(struct platform_device *pdev)
{
struct s3c_chip *s3c = platform_get_drvdata(pdev);
int err;
@@ -327,7 +327,7 @@ static struct platform_driver s3c_pwm_driver = {
.owner = THIS_MODULE,
},
.probe = s3c_pwm_probe,
- .remove = __devexit_p(s3c_pwm_remove),
+ .remove = s3c_pwm_remove,
.suspend = s3c_pwm_suspend,
.resume = s3c_pwm_resume,
};
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 057465e0553c..30c0e2b70ce8 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -210,7 +210,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit tegra_pwm_remove(struct platform_device *pdev)
+static int tegra_pwm_remove(struct platform_device *pdev)
{
struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
int i;
@@ -249,7 +249,7 @@ static struct platform_driver tegra_pwm_driver = {
.of_match_table = of_match_ptr(tegra_pwm_of_match),
},
.probe = tegra_pwm_probe,
- .remove = __devexit_p(tegra_pwm_remove),
+ .remove = tegra_pwm_remove,
};
module_platform_driver(tegra_pwm_driver);
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index d6d4cf05565e..87c091b245cc 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -184,7 +184,7 @@ static const struct pwm_ops ecap_pwm_ops = {
.owner = THIS_MODULE,
};
-static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+static int ecap_pwm_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
@@ -235,7 +235,7 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ecap_pwm_remove(struct platform_device *pdev)
+static int ecap_pwm_remove(struct platform_device *pdev)
{
struct ecap_pwm_chip *pc = platform_get_drvdata(pdev);
@@ -249,7 +249,7 @@ static struct platform_driver ecap_pwm_driver = {
.name = "ecap",
},
.probe = ecap_pwm_probe,
- .remove = __devexit_p(ecap_pwm_remove),
+ .remove = ecap_pwm_remove,
};
module_platform_driver(ecap_pwm_driver);
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index d3c1dff0a0dc..9ffd389d0c8b 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -392,7 +392,7 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
.owner = THIS_MODULE,
};
-static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+static int ehrpwm_pwm_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
@@ -443,7 +443,7 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
+static int ehrpwm_pwm_remove(struct platform_device *pdev)
{
struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
@@ -457,7 +457,7 @@ static struct platform_driver ehrpwm_pwm_driver = {
.name = "ehrpwm",
},
.probe = ehrpwm_pwm_probe,
- .remove = __devexit_p(ehrpwm_pwm_remove),
+ .remove = ehrpwm_pwm_remove,
};
module_platform_driver(ehrpwm_pwm_driver);
diff --git a/drivers/pwm/pwm-twl6030.c b/drivers/pwm/pwm-twl6030.c
index 8e6387864ca2..378a7e286366 100644
--- a/drivers/pwm/pwm-twl6030.c
+++ b/drivers/pwm/pwm-twl6030.c
@@ -176,7 +176,7 @@ static struct platform_driver twl6030_pwm_driver = {
.name = "twl6030-pwm",
},
.probe = twl6030_pwm_probe,
- .remove = __devexit_p(twl6030_pwm_remove),
+ .remove = twl6030_pwm_remove,
};
module_platform_driver(twl6030_pwm_driver);
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 38ecd8f4d60e..6faba406b6e9 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2202,7 +2202,7 @@ static void tsi721_disable_ints(struct tsi721_device *priv)
*
* Configures Tsi721 as RapidIO master port.
*/
-static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
+static int tsi721_setup_mport(struct tsi721_device *priv)
{
struct pci_dev *pdev = priv->pdev;
int err = 0;
@@ -2302,7 +2302,7 @@ err_exit:
return err;
}
-static int __devinit tsi721_probe(struct pci_dev *pdev,
+static int tsi721_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct tsi721_device *priv;
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h
index 7d5b13ba8d4f..b4b0d83f9ef6 100644
--- a/drivers/rapidio/devices/tsi721.h
+++ b/drivers/rapidio/devices/tsi721.h
@@ -846,7 +846,7 @@ struct tsi721_device {
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
extern void tsi721_bdma_handler(struct tsi721_bdma_chan *bdma_chan);
-extern int __devinit tsi721_register_dma(struct tsi721_device *priv);
+extern int tsi721_register_dma(struct tsi721_device *priv);
#endif
#endif
diff --git a/drivers/rapidio/devices/tsi721_dma.c b/drivers/rapidio/devices/tsi721_dma.c
index 92e06a5c62ec..502663f5f7c6 100644
--- a/drivers/rapidio/devices/tsi721_dma.c
+++ b/drivers/rapidio/devices/tsi721_dma.c
@@ -765,7 +765,7 @@ static int tsi721_device_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
return 0;
}
-int __devinit tsi721_register_dma(struct tsi721_device *priv)
+int tsi721_register_dma(struct tsi721_device *priv)
{
int i;
int nr_channels = TSI721_DMA_MAXCH;
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 07da58bb495c..a965acd3c0e4 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -371,7 +371,7 @@ static void rio_switch_init(struct rio_dev *rdev, int do_enum)
* device to the RIO device list. Creates the generic sysfs nodes
* for an RIO device.
*/
-static int __devinit rio_add_device(struct rio_dev *rdev)
+static int rio_add_device(struct rio_dev *rdev)
{
int err;
@@ -463,7 +463,7 @@ inline int rio_enable_rx_tx_port(struct rio_mport *port,
* to a RIO device on success or NULL on failure.
*
*/
-static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
+static struct rio_dev *rio_setup_device(struct rio_net *net,
struct rio_mport *port, u16 destid,
u8 hopcount, int do_enum)
{
@@ -837,7 +837,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
* Recursively enumerates a RIO network. Transactions are sent via the
* master port passed in @port.
*/
-static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
u8 hopcount, struct rio_dev *prev, int prev_port)
{
struct rio_dev *rdev;
@@ -1044,7 +1044,7 @@ static int rio_enum_complete(struct rio_mport *port)
* Recursively discovers a RIO network. Transactions are sent via the
* master port passed in @port.
*/
-static int __devinit
+static int
rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
u8 hopcount, struct rio_dev *prev, int prev_port)
{
@@ -1151,7 +1151,7 @@ static int rio_mport_is_active(struct rio_mport *port)
* network list of associated master ports. Returns a
* RIO network pointer on success or %NULL on failure.
*/
-static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port,
+static struct rio_net *rio_alloc_net(struct rio_mport *port,
int do_enum, u16 start)
{
struct rio_net *net;
@@ -1266,7 +1266,7 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
* link, then start recursive peer enumeration. Returns %0 if
* enumeration succeeds or %-EBUSY if enumeration fails.
*/
-int __devinit rio_enum_mport(struct rio_mport *mport)
+int rio_enum_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
int rc = 0;
@@ -1369,7 +1369,7 @@ static void rio_build_route_tables(struct rio_net *net)
* peer discovery. Returns %0 if discovery succeeds or %-EBUSY
* on failure.
*/
-int __devinit rio_disc_mport(struct rio_mport *mport)
+int rio_disc_mport(struct rio_mport *mport)
{
struct rio_net *net = NULL;
unsigned long to_end;
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 0c6fcb461faf..d553b5d13722 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1250,7 +1250,7 @@ static void rio_fixup_device(struct rio_dev *dev)
{
}
-static int __devinit rio_init(void)
+static int rio_init(void)
{
struct rio_dev *dev = NULL;
@@ -1267,7 +1267,7 @@ struct rio_disc_work {
struct rio_mport *mport;
};
-static void __devinit disc_work_handler(struct work_struct *_work)
+static void disc_work_handler(struct work_struct *_work)
{
struct rio_disc_work *work;
@@ -1277,7 +1277,7 @@ static void __devinit disc_work_handler(struct work_struct *_work)
rio_disc_mport(work->mport);
}
-int __devinit rio_init_mports(void)
+int rio_init_mports(void)
{
struct rio_mport *port;
struct rio_disc_work *work;
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index e7a4780e93db..9e198e590675 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -120,15 +120,11 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
return vq;
}
-static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
{
struct virtqueue *vq, *n;
- struct rproc *rproc = vdev_to_rproc(vdev);
struct rproc_vring *rvring;
- /* power down the remote processor before deleting vqs */
- rproc_shutdown(rproc);
-
list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
rvring = vq->priv;
rvring->vq = NULL;
@@ -137,6 +133,16 @@ static void rproc_virtio_del_vqs(struct virtio_device *vdev)
}
}
+static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+{
+ struct rproc *rproc = vdev_to_rproc(vdev);
+
+ /* power down the remote processor before deleting vqs */
+ rproc_shutdown(rproc);
+
+ __rproc_virtio_del_vqs(vdev);
+}
+
static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
struct virtqueue *vqs[],
vq_callback_t *callbacks[],
@@ -163,7 +169,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
return 0;
error:
- rproc_virtio_del_vqs(vdev);
+ __rproc_virtio_del_vqs(vdev);
return ret;
}
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
index 7a82337e4dee..073108dcf9e7 100644
--- a/drivers/rtc/rtc-tps65910.c
+++ b/drivers/rtc/rtc-tps65910.c
@@ -288,11 +288,11 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
{
/* leave rtc running, but disable irqs */
- struct rtc_device *rtc = platform_get_drvdata(pdev);
+ struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);
- tps65910_rtc_alarm_irq_enable(&rtc->dev, 0);
+ tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);
- rtc_device_unregister(rtc);
+ rtc_device_unregister(tps_rtc->rtc);
return 0;
}
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index c1bafc3f3fb1..9594ab62702b 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
frame_index,
(void **)&frame_buffer);
- sci_controller_copy_sata_response(&ireq->stp.req,
+ sci_controller_copy_sata_response(&ireq->stp.rsp,
frame_header,
frame_buffer);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 16b7a72a70c4..3b2365c8eab2 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1276,7 +1276,7 @@ struct megasas_evt_detail {
} __attribute__ ((packed));
struct megasas_aen_event {
- struct work_struct hotplug_work;
+ struct delayed_work hotplug_work;
struct megasas_instance *instance;
};
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index d2c5366aff7f..e4f2baacf1e1 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -2060,9 +2060,9 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
} else {
ev->instance = instance;
instance->ev = ev;
- INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
- schedule_delayed_work(
- (struct delayed_work *)&ev->hotplug_work, 0);
+ INIT_DELAYED_WORK(&ev->hotplug_work,
+ megasas_aen_polling);
+ schedule_delayed_work(&ev->hotplug_work, 0);
}
}
}
@@ -4352,8 +4352,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
/* cancel the delayed work if this work still in queue */
if (instance->ev != NULL) {
struct megasas_aen_event *ev = instance->ev;
- cancel_delayed_work_sync(
- (struct delayed_work *)&ev->hotplug_work);
+ cancel_delayed_work_sync(&ev->hotplug_work);
instance->ev = NULL;
}
@@ -4545,8 +4544,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
/* cancel the delayed work if this work still in queue*/
if (instance->ev != NULL) {
struct megasas_aen_event *ev = instance->ev;
- cancel_delayed_work_sync(
- (struct delayed_work *)&ev->hotplug_work);
+ cancel_delayed_work_sync(&ev->hotplug_work);
instance->ev = NULL;
}
@@ -5190,7 +5188,7 @@ static void
megasas_aen_polling(struct work_struct *work)
{
struct megasas_aen_event *ev =
- container_of(work, struct megasas_aen_event, hotplug_work);
+ container_of(work, struct megasas_aen_event, hotplug_work.work);
struct megasas_instance *instance = ev->instance;
union megasas_evt_class_locale class_locale;
struct Scsi_Host *host;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2936b447cae9..2c0d0ec8150b 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
#include <linux/cpu.h>
#include <linux/mutex.h>
#include <linux/async.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -1062,6 +1063,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
/**
+ * scsi_report_opcode - Find out if a given command opcode is supported
+ * @sdev: scsi device to query
+ * @buffer: scratch buffer (must be at least 20 bytes long)
+ * @len: length of buffer
+ * @opcode: opcode for command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
+ * opcode. Returns 0 if RSOC fails or if the command opcode is
+ * unsupported. Returns 1 if the device claims to support the command.
+ */
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+ unsigned int len, unsigned char opcode)
+{
+ unsigned char cmd[16];
+ struct scsi_sense_hdr sshdr;
+ int result;
+
+ if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
+ return 0;
+
+ memset(cmd, 0, 16);
+ cmd[0] = MAINTENANCE_IN;
+ cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
+ cmd[2] = 1; /* One command format */
+ cmd[3] = opcode;
+ put_unaligned_be32(len, &cmd[6]);
+ memset(buffer, 0, len);
+
+ result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+ &sshdr, 30 * HZ, 3, NULL);
+
+ if (result && scsi_sense_valid(&sshdr) &&
+ sshdr.sense_key == ILLEGAL_REQUEST &&
+ (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
+ return 0;
+
+ if ((buffer[1] & 3) == 3) /* Command supported */
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(scsi_report_opcode);
+
+/**
* scsi_device_get - get an additional reference to a scsi_device
* @sdev: device to get a reference to
*
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index da36a3a81a9e..9032e910bca3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
action = ACTION_FAIL;
error = -EILSEQ;
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
- } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
- (cmd->cmnd[0] == UNMAP ||
- cmd->cmnd[0] == WRITE_SAME_16 ||
- cmd->cmnd[0] == WRITE_SAME)) {
- description = "Discard failure";
+ } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+ switch (cmd->cmnd[0]) {
+ case UNMAP:
+ description = "Discard failure";
+ break;
+ case WRITE_SAME:
+ case WRITE_SAME_16:
+ if (cmd->cmnd[1] & 0x8)
+ description = "Discard failure";
+ else
+ description =
+ "Write same failure";
+ break;
+ default:
+ description = "Invalid command failure";
+ break;
+ }
action = ACTION_FAIL;
error = -EREMOTEIO;
} else
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 12f6fdfc1147..352bc77b7c88 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
#endif
static void sd_config_discard(struct scsi_disk *, unsigned int);
+static void sd_config_write_same(struct scsi_disk *);
static int sd_revalidate_disk(struct gendisk *);
static void sd_unlock_native_capacity(struct gendisk *disk);
static int sd_probe(struct device *);
@@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
return err ? err : count;
}
+static ssize_t
+sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+}
+
+static ssize_t
+sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdp = sdkp->device;
+ unsigned long max;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (sdp->type != TYPE_DISK)
+ return -EINVAL;
+
+ err = kstrtoul(buf, 10, &max);
+
+ if (err)
+ return err;
+
+ if (max == 0)
+ sdp->no_write_same = 1;
+ else if (max <= SD_MAX_WS16_BLOCKS)
+ sdkp->max_ws_blocks = max;
+
+ sd_config_write_same(sdkp);
+
+ return count;
+}
+
static struct device_attribute sd_disk_attrs[] = {
__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
sd_store_cache_type),
@@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
sd_store_provisioning_mode),
+ __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
+ sd_show_write_same_blocks, sd_store_write_same_blocks),
__ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
sd_show_max_medium_access_timeouts,
sd_store_max_medium_access_timeouts),
@@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
return;
case SD_LBP_UNMAP:
- max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+ max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
break;
case SD_LBP_WS16:
- max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+ max_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
break;
case SD_LBP_WS10:
- max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+ max_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
break;
case SD_LBP_ZERO:
- max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+ max_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
q->limits.discard_zeroes_data = 1;
break;
}
@@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
}
/**
- * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
+ * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device
* @sdp: scsi device to operate one
* @rq: Request to prepare
*
* Will issue either UNMAP or WRITE SAME(16) depending on preference
* indicated by target device.
**/
-static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
{
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
- struct bio *bio = rq->bio;
- sector_t sector = bio->bi_sector;
- unsigned int nr_sectors = bio_sectors(bio);
+ sector_t sector = blk_rq_pos(rq);
+ unsigned int nr_sectors = blk_rq_sectors(rq);
+ unsigned int nr_bytes = blk_rq_bytes(rq);
unsigned int len;
int ret;
char *buf;
struct page *page;
- if (sdkp->device->sector_size == 4096) {
- sector >>= 3;
- nr_sectors >>= 3;
- }
-
+ sector >>= ilog2(sdp->sector_size) - 9;
+ nr_sectors >>= ilog2(sdp->sector_size) - 9;
rq->timeout = SD_TIMEOUT;
memset(rq->cmd, 0, rq->cmd_len);
@@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
blk_add_request_payload(rq, page, len);
ret = scsi_setup_blk_pc_cmnd(sdp, rq);
rq->buffer = page_address(page);
+ rq->__data_len = nr_bytes;
out:
if (ret != BLKPREP_OK) {
@@ -669,6 +713,83 @@ out:
return ret;
}
+static void sd_config_write_same(struct scsi_disk *sdkp)
+{
+ struct request_queue *q = sdkp->disk->queue;
+ unsigned int logical_block_size = sdkp->device->sector_size;
+ unsigned int blocks = 0;
+
+ if (sdkp->device->no_write_same) {
+ sdkp->max_ws_blocks = 0;
+ goto out;
+ }
+
+ /* Some devices can not handle block counts above 0xffff despite
+ * supporting WRITE SAME(16). Consequently we default to 64k
+ * blocks per I/O unless the device explicitly advertises a
+ * bigger limit.
+ */
+ if (sdkp->max_ws_blocks == 0)
+ sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
+
+ if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+ blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
+ else
+ blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
+
+out:
+ blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+}
+
+/**
+ * sd_setup_write_same_cmnd - write the same data to multiple blocks
+ * @sdp: scsi device to operate one
+ * @rq: Request to prepare
+ *
+ * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
+ * preference indicated by target device.
+ **/
+static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+{
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ struct bio *bio = rq->bio;
+ sector_t sector = blk_rq_pos(rq);
+ unsigned int nr_sectors = blk_rq_sectors(rq);
+ unsigned int nr_bytes = blk_rq_bytes(rq);
+ int ret;
+
+ if (sdkp->device->no_write_same)
+ return BLKPREP_KILL;
+
+ BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+
+ sector >>= ilog2(sdp->sector_size) - 9;
+ nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+ rq->__data_len = sdp->sector_size;
+ rq->timeout = SD_WRITE_SAME_TIMEOUT;
+ memset(rq->cmd, 0, rq->cmd_len);
+
+ if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
+ rq->cmd_len = 16;
+ rq->cmd[0] = WRITE_SAME_16;
+ put_unaligned_be64(sector, &rq->cmd[2]);
+ put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+ } else {
+ rq->cmd_len = 10;
+ rq->cmd[0] = WRITE_SAME;
+ put_unaligned_be32(sector, &rq->cmd[2]);
+ put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+ }
+
+ ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+ rq->__data_len = nr_bytes;
+
+ return ret;
+}
+
static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
{
rq->timeout = SD_FLUSH_TIMEOUT;
@@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
* block PC requests to make life easier.
*/
if (rq->cmd_flags & REQ_DISCARD) {
- ret = scsi_setup_discard_cmnd(sdp, rq);
+ ret = sd_setup_discard_cmnd(sdp, rq);
+ goto out;
+ } else if (rq->cmd_flags & REQ_WRITE_SAME) {
+ ret = sd_setup_write_same_cmnd(sdp, rq);
goto out;
} else if (rq->cmd_flags & REQ_FLUSH) {
ret = scsi_setup_flush_cmnd(sdp, rq);
@@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
struct scsi_sense_hdr sshdr;
struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+ struct request *req = SCpnt->request;
int sense_valid = 0;
int sense_deferred = 0;
unsigned char op = SCpnt->cmnd[0];
+ unsigned char unmap = SCpnt->cmnd[1] & 8;
- if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
- scsi_set_resid(SCpnt, 0);
+ if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
+ if (!result) {
+ good_bytes = blk_rq_bytes(req);
+ scsi_set_resid(SCpnt, 0);
+ } else {
+ good_bytes = 0;
+ scsi_set_resid(SCpnt, blk_rq_bytes(req));
+ }
+ }
if (result) {
sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt)
if (sshdr.asc == 0x10) /* DIX: Host detected corruption */
good_bytes = sd_completed_bytes(SCpnt);
/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
- if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
- (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
- sd_config_discard(sdkp, SD_LBP_DISABLE);
+ if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+ switch (op) {
+ case UNMAP:
+ sd_config_discard(sdkp, SD_LBP_DISABLE);
+ break;
+ case WRITE_SAME_16:
+ case WRITE_SAME:
+ if (unmap)
+ sd_config_discard(sdkp, SD_LBP_DISABLE);
+ else {
+ sdkp->device->no_write_same = 1;
+ sd_config_write_same(sdkp);
+
+ good_bytes = 0;
+ req->__data_len = blk_rq_bytes(req);
+ req->cmd_flags |= REQ_QUIET;
+ }
+ }
+ }
break;
default:
break;
@@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
if (buffer[3] == 0x3c) {
unsigned int lba_count, desc_count;
- sdkp->max_ws_blocks =
- (u32) min_not_zero(get_unaligned_be64(&buffer[36]),
- (u64)0xffffffff);
+ sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
if (!sdkp->lbpme)
goto out;
@@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
kfree(buffer);
}
+static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+ if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
+ WRITE_SAME_16))
+ sdkp->ws16 = 1;
+}
+
static int sd_try_extended_inquiry(struct scsi_device *sdp)
{
/*
@@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_write_protect_flag(sdkp, buffer);
sd_read_cache_type(sdkp, buffer);
sd_read_app_tag_own(sdkp, buffer);
+ sd_read_write_same(sdkp, buffer);
}
sdkp->first_scan = 0;
@@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
blk_queue_flush(sdkp->disk->queue, flush);
set_capacity(disk, sdkp->capacity);
+ sd_config_write_same(sdkp);
kfree(buffer);
out:
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 47c52a6d733c..74a1e4ca5401 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -14,6 +14,7 @@
#define SD_TIMEOUT (30 * HZ)
#define SD_MOD_TIMEOUT (75 * HZ)
#define SD_FLUSH_TIMEOUT (60 * HZ)
+#define SD_WRITE_SAME_TIMEOUT (120 * HZ)
/*
* Number of allowed retries
@@ -39,6 +40,11 @@ enum {
};
enum {
+ SD_MAX_WS10_BLOCKS = 0xffff,
+ SD_MAX_WS16_BLOCKS = 0x7fffff,
+};
+
+enum {
SD_LBP_FULL = 0, /* Full logical block provisioning */
SD_LBP_UNMAP, /* Use UNMAP command */
SD_LBP_WS16, /* Use WRITE SAME(16) with UNMAP bit */
@@ -77,6 +83,7 @@ struct scsi_disk {
unsigned lbpws : 1;
unsigned lbpws10 : 1;
unsigned lbpvpd : 1;
+ unsigned ws16 : 1;
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 84c2861d6f4d..718cc1f49230 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -35,6 +35,8 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
static void spidev_release(struct device *dev)
{
@@ -93,6 +95,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
if (of_driver_match_device(dev, drv))
return 1;
+ /* Then try ACPI */
+ if (acpi_driver_match_device(dev, drv))
+ return 1;
+
if (sdrv->id_table)
return !!spi_match_id(sdrv->id_table, spi);
@@ -819,7 +825,7 @@ static void of_register_spi_devices(struct spi_master *master)
if (!master->dev.of_node)
return;
- for_each_child_of_node(master->dev.of_node, nc) {
+ for_each_available_child_of_node(master->dev.of_node, nc) {
/* Alloc an spi_device */
spi = spi_alloc_device(master);
if (!spi) {
@@ -888,6 +894,100 @@ static void of_register_spi_devices(struct spi_master *master)
static void of_register_spi_devices(struct spi_master *master) { }
#endif
+#ifdef CONFIG_ACPI
+static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
+{
+ struct spi_device *spi = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ struct acpi_resource_spi_serialbus *sb;
+
+ sb = &ares->data.spi_serial_bus;
+ if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
+ spi->chip_select = sb->device_selection;
+ spi->max_speed_hz = sb->connection_speed;
+
+ if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
+ spi->mode |= SPI_CPHA;
+ if (sb->clock_polarity == ACPI_SPI_START_HIGH)
+ spi->mode |= SPI_CPOL;
+ if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH)
+ spi->mode |= SPI_CS_HIGH;
+ }
+ } else if (spi->irq < 0) {
+ struct resource r;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &r))
+ spi->irq = r.start;
+ }
+
+ /* Always tell the ACPI core to skip this resource */
+ return 1;
+}
+
+static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
+ void *data, void **return_value)
+{
+ struct spi_master *master = data;
+ struct list_head resource_list;
+ struct acpi_device *adev;
+ struct spi_device *spi;
+ int ret;
+
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+ if (acpi_bus_get_status(adev) || !adev->status.present)
+ return AE_OK;
+
+ spi = spi_alloc_device(master);
+ if (!spi) {
+ dev_err(&master->dev, "failed to allocate SPI device for %s\n",
+ dev_name(&adev->dev));
+ return AE_NO_MEMORY;
+ }
+
+ ACPI_HANDLE_SET(&spi->dev, handle);
+ spi->irq = -1;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ acpi_spi_add_resource, spi);
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (ret < 0 || !spi->max_speed_hz) {
+ spi_dev_put(spi);
+ return AE_OK;
+ }
+
+ strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
+ if (spi_add_device(spi)) {
+ dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
+ dev_name(&adev->dev));
+ spi_dev_put(spi);
+ }
+
+ return AE_OK;
+}
+
+static void acpi_register_spi_devices(struct spi_master *master)
+{
+ acpi_status status;
+ acpi_handle handle;
+
+ handle = ACPI_HANDLE(&master->dev);
+ if (!handle)
+ return;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_spi_add_device, NULL,
+ master, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(&master->dev, "failed to enumerate SPI slaves\n");
+}
+#else
+static inline void acpi_register_spi_devices(struct spi_master *master) {}
+#endif /* CONFIG_ACPI */
+
static void spi_master_release(struct device *dev)
{
struct spi_master *master;
@@ -1023,8 +1123,9 @@ int spi_register_master(struct spi_master *master)
spi_match_master_to_boardinfo(master, &bi->board_info);
mutex_unlock(&board_lock);
- /* Register devices from the device tree */
+ /* Register devices from the device tree and ACPI */
of_register_spi_devices(master);
+ acpi_register_spi_devices(master);
done:
return status;
}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 9097155e9ebe..dcecbfb17243 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1819,8 +1819,10 @@ void target_execute_cmd(struct se_cmd *cmd)
/*
* If the received CDB has aleady been aborted stop processing it here.
*/
- if (transport_check_aborted_status(cmd, 1))
+ if (transport_check_aborted_status(cmd, 1)) {
+ complete(&cmd->t_transport_stop_comp);
return;
+ }
/*
* Determine if IOCTL context caller in requesting the stopping of this
@@ -3067,7 +3069,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
unsigned long flags;
spin_lock_irqsave(&cmd->t_state_lock, flags);
- if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+ if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION | SCF_SENT_DELAYED_TAS)) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
return;
}
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 3d7e1ee2fa57..65f891be12d1 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -39,6 +39,7 @@
#include <linux/atmel_pdc.h>
#include <linux/atmel_serial.h>
#include <linux/uaccess.h>
+#include <linux/pinctrl/consumer.h>
#include <asm/io.h>
#include <asm/ioctls.h>
@@ -1773,6 +1774,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
struct atmel_uart_data *pdata = pdev->dev.platform_data;
void *data;
int ret = -ENODEV;
+ struct pinctrl *pinctrl;
BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
@@ -1805,6 +1807,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
atmel_init_port(port, pdev);
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ ret = PTR_ERR(pinctrl);
+ goto err;
+ }
+
if (!atmel_use_dma_rx(&port->uart)) {
ret = -ENOMEM;
data = kmalloc(sizeof(struct atmel_uart_char)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index f87d7e8964bf..4e0d0c3734b3 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -539,25 +539,25 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
{
unsigned short *p = (unsigned short *) vc->vc_pos;
- scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
+ scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) p,
- (vc->vc_cols - vc->vc_x) / 2 + 1);
+ vc->vc_cols - vc->vc_x);
}
static void delete_char(struct vc_data *vc, unsigned int nr)
{
unsigned short *p = (unsigned short *) vc->vc_pos;
- scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
+ scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);
scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
nr * 2);
vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) p,
- (vc->vc_cols - vc->vc_x) / 2);
+ vc->vc_cols - vc->vc_x);
}
static int softcursor_original;
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 6f3ea9bbc818..82e2b89d4480 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -44,6 +44,22 @@ config UIO_PDRV_GENIRQ
If you don't know what to do here, say N.
+config UIO_DMEM_GENIRQ
+ tristate "Userspace platform driver with generic irq and dynamic memory"
+ help
+ Platform driver for Userspace I/O devices, including generic
+ interrupt handling code. Shared interrupts are not supported.
+
+ Memory regions can be specified with the same platform device
+ resources as the UIO_PDRV drivers, but dynamic regions can also
+ be specified.
+ The number and size of these regions is static,
+ but the memory allocation is not performed until
+ the associated device file is opened. The
+ memory is freed once the uio device is closed.
+
+ If you don't know what to do here, say N.
+
config UIO_AEC
tristate "AEC video timestamp device"
depends on PCI
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index d4dd9a5552f8..b354c539507a 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o
obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
+obj-$(CONFIG_UIO_DMEM_GENIRQ) += uio_dmem_genirq.o
obj-$(CONFIG_UIO_AEC) += uio_aec.o
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
index 72b22d44e8b9..1548982db58b 100644
--- a/drivers/uio/uio_aec.c
+++ b/drivers/uio/uio_aec.c
@@ -78,7 +78,7 @@ static void print_board_data(struct pci_dev *pdev, struct uio_info *i)
ioread8(i->priv + 0x07));
}
-static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct uio_info *info;
int ret;
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index a84a451159ed..7dd6fc60539d 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -40,7 +40,7 @@ static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
return IRQ_HANDLED;
}
-static int __devinit hilscher_pci_probe(struct pci_dev *dev,
+static int hilscher_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct uio_info *info;
@@ -112,7 +112,7 @@ static void hilscher_pci_remove(struct pci_dev *dev)
kfree (info);
}
-static struct pci_device_id hilscher_pci_ids[] __devinitdata = {
+static struct pci_device_id hilscher_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9030,
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
new file mode 100644
index 000000000000..252434c9ea9d
--- /dev/null
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -0,0 +1,359 @@
+/*
+ * drivers/uio/uio_dmem_genirq.c
+ *
+ * Userspace I/O platform driver with generic IRQ handling code.
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * Based on uio_pdrv_genirq.c by Magnus Damm
+ *
+ * This program is free software; you can 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/uio_driver.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_data/uio_dmem_genirq.h>
+#include <linux/stringify.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#define DRIVER_NAME "uio_dmem_genirq"
+#define DMEM_MAP_ERROR (~0)
+
+struct uio_dmem_genirq_platdata {
+ struct uio_info *uioinfo;
+ spinlock_t lock;
+ unsigned long flags;
+ struct platform_device *pdev;
+ unsigned int dmem_region_start;
+ unsigned int num_dmem_regions;
+ void *dmem_region_vaddr[MAX_UIO_MAPS];
+ struct mutex alloc_lock;
+ unsigned int refcnt;
+};
+
+static int uio_dmem_genirq_open(struct uio_info *info, struct inode *inode)
+{
+ struct uio_dmem_genirq_platdata *priv = info->priv;
+ struct uio_mem *uiomem;
+ int ret = 0;
+ int dmem_region = priv->dmem_region_start;
+
+ uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+ mutex_lock(&priv->alloc_lock);
+ while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+ void *addr;
+ if (!uiomem->size)
+ break;
+
+ addr = dma_alloc_coherent(&priv->pdev->dev, uiomem->size,
+ (dma_addr_t *)&uiomem->addr, GFP_KERNEL);
+ if (!addr) {
+ uiomem->addr = DMEM_MAP_ERROR;
+ }
+ priv->dmem_region_vaddr[dmem_region++] = addr;
+ ++uiomem;
+ }
+ priv->refcnt++;
+
+ mutex_unlock(&priv->alloc_lock);
+ /* Wait until the Runtime PM code has woken up the device */
+ pm_runtime_get_sync(&priv->pdev->dev);
+ return ret;
+}
+
+static int uio_dmem_genirq_release(struct uio_info *info, struct inode *inode)
+{
+ struct uio_dmem_genirq_platdata *priv = info->priv;
+ struct uio_mem *uiomem;
+ int dmem_region = priv->dmem_region_start;
+
+ /* Tell the Runtime PM code that the device has become idle */
+ pm_runtime_put_sync(&priv->pdev->dev);
+
+ uiomem = &priv->uioinfo->mem[priv->dmem_region_start];
+
+ mutex_lock(&priv->alloc_lock);
+
+ priv->refcnt--;
+ while (!priv->refcnt && uiomem < &priv->uioinfo->mem[MAX_UIO_MAPS]) {
+ if (!uiomem->size)
+ break;
+ if (priv->dmem_region_vaddr[dmem_region]) {
+ dma_free_coherent(&priv->pdev->dev, uiomem->size,
+ priv->dmem_region_vaddr[dmem_region],
+ uiomem->addr);
+ }
+ uiomem->addr = DMEM_MAP_ERROR;
+ ++dmem_region;
+ ++uiomem;
+ }
+
+ mutex_unlock(&priv->alloc_lock);
+ return 0;
+}
+
+static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info)
+{
+ struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+
+ /* Just disable the interrupt in the interrupt controller, and
+ * remember the state so we can allow user space to enable it later.
+ */
+
+ if (!test_and_set_bit(0, &priv->flags))
+ disable_irq_nosync(irq);
+
+ return IRQ_HANDLED;
+}
+
+static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
+{
+ struct uio_dmem_genirq_platdata *priv = dev_info->priv;
+ unsigned long flags;
+
+ /* Allow user space to enable and disable the interrupt
+ * in the interrupt controller, but keep track of the
+ * state to prevent per-irq depth damage.
+ *
+ * Serialize this operation to support multiple tasks.
+ */
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (irq_on) {
+ if (test_and_clear_bit(0, &priv->flags))
+ enable_irq(dev_info->irq);
+ } else {
+ if (!test_and_set_bit(0, &priv->flags))
+ disable_irq(dev_info->irq);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int uio_dmem_genirq_probe(struct platform_device *pdev)
+{
+ struct uio_dmem_genirq_pdata *pdata = pdev->dev.platform_data;
+ struct uio_info *uioinfo = &pdata->uioinfo;
+ struct uio_dmem_genirq_platdata *priv;
+ struct uio_mem *uiomem;
+ int ret = -EINVAL;
+ int i;
+
+ if (pdev->dev.of_node) {
+ int irq;
+
+ /* alloc uioinfo for one device */
+ uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+ if (!uioinfo) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "unable to kmalloc\n");
+ goto bad2;
+ }
+ uioinfo->name = pdev->dev.of_node->name;
+ uioinfo->version = "devicetree";
+
+ /* Multiple IRQs are not supported */
+ irq = platform_get_irq(pdev, 0);
+ if (irq == -ENXIO)
+ uioinfo->irq = UIO_IRQ_NONE;
+ else
+ uioinfo->irq = irq;
+ }
+
+ if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+ dev_err(&pdev->dev, "missing platform_data\n");
+ goto bad0;
+ }
+
+ if (uioinfo->handler || uioinfo->irqcontrol ||
+ uioinfo->irq_flags & IRQF_SHARED) {
+ dev_err(&pdev->dev, "interrupt configuration error\n");
+ goto bad0;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "unable to kmalloc\n");
+ goto bad0;
+ }
+
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+ priv->uioinfo = uioinfo;
+ spin_lock_init(&priv->lock);
+ priv->flags = 0; /* interrupt is enabled to begin with */
+ priv->pdev = pdev;
+ mutex_init(&priv->alloc_lock);
+
+ 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) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags != IORESOURCE_MEM)
+ continue;
+
+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+ dev_warn(&pdev->dev, "device has more than "
+ __stringify(MAX_UIO_MAPS)
+ " I/O memory resources.\n");
+ break;
+ }
+
+ uiomem->memtype = UIO_MEM_PHYS;
+ uiomem->addr = r->start;
+ uiomem->size = resource_size(r);
+ ++uiomem;
+ }
+
+ priv->dmem_region_start = i;
+ priv->num_dmem_regions = pdata->num_dynamic_regions;
+
+ for (i = 0; i < pdata->num_dynamic_regions; ++i) {
+ if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+ dev_warn(&pdev->dev, "device has more than "
+ __stringify(MAX_UIO_MAPS)
+ " dynamic and fixed memory regions.\n");
+ break;
+ }
+ uiomem->memtype = UIO_MEM_PHYS;
+ uiomem->addr = DMEM_MAP_ERROR;
+ uiomem->size = pdata->dynamic_region_sizes[i];
+ ++uiomem;
+ }
+
+ while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+ uiomem->size = 0;
+ ++uiomem;
+ }
+
+ /* This driver requires no hardware specific kernel code to handle
+ * interrupts. Instead, the interrupt handler simply disables the
+ * interrupt in the interrupt controller. User space is responsible
+ * for performing hardware specific acknowledge and re-enabling of
+ * the interrupt in the interrupt controller.
+ *
+ * Interrupt sharing is not supported.
+ */
+
+ uioinfo->handler = uio_dmem_genirq_handler;
+ uioinfo->irqcontrol = uio_dmem_genirq_irqcontrol;
+ uioinfo->open = uio_dmem_genirq_open;
+ uioinfo->release = uio_dmem_genirq_release;
+ uioinfo->priv = priv;
+
+ /* Enable Runtime PM for this device:
+ * The device starts in suspended state to allow the hardware to be
+ * turned off by default. The Runtime PM bus code should power on the
+ * hardware and enable clocks at open().
+ */
+ pm_runtime_enable(&pdev->dev);
+
+ ret = uio_register_device(&pdev->dev, priv->uioinfo);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to register uio device\n");
+ goto bad1;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ return 0;
+ bad1:
+ kfree(priv);
+ pm_runtime_disable(&pdev->dev);
+ bad0:
+ /* kfree uioinfo for OF */
+ if (pdev->dev.of_node)
+ kfree(uioinfo);
+ bad2:
+ return ret;
+}
+
+static int uio_dmem_genirq_remove(struct platform_device *pdev)
+{
+ struct uio_dmem_genirq_platdata *priv = platform_get_drvdata(pdev);
+
+ uio_unregister_device(priv->uioinfo);
+ pm_runtime_disable(&pdev->dev);
+
+ priv->uioinfo->handler = NULL;
+ priv->uioinfo->irqcontrol = NULL;
+
+ /* kfree uioinfo for OF */
+ if (pdev->dev.of_node)
+ kfree(priv->uioinfo);
+
+ kfree(priv);
+ return 0;
+}
+
+static int uio_dmem_genirq_runtime_nop(struct device *dev)
+{
+ /* Runtime PM callback shared between ->runtime_suspend()
+ * and ->runtime_resume(). Simply returns success.
+ *
+ * In this driver pm_runtime_get_sync() and pm_runtime_put_sync()
+ * are used at open() and release() time. This allows the
+ * Runtime PM code to turn off power to the device while the
+ * device is unused, ie before open() and after release().
+ *
+ * This Runtime PM callback does not need to save or restore
+ * any registers since user space is responsbile for hardware
+ * register reinitialization after open().
+ */
+ return 0;
+}
+
+static const struct dev_pm_ops uio_dmem_genirq_dev_pm_ops = {
+ .runtime_suspend = uio_dmem_genirq_runtime_nop,
+ .runtime_resume = uio_dmem_genirq_runtime_nop,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id uio_of_genirq_match[] = {
+ { /* empty for now */ },
+};
+MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
+#else
+# define uio_of_genirq_match NULL
+#endif
+
+static struct platform_driver uio_dmem_genirq = {
+ .probe = uio_dmem_genirq_probe,
+ .remove = uio_dmem_genirq_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &uio_dmem_genirq_dev_pm_ops,
+ .of_match_table = uio_of_genirq_match,
+ },
+};
+
+module_platform_driver(uio_dmem_genirq);
+
+MODULE_AUTHOR("Damian Hobson-Garcia");
+MODULE_DESCRIPTION("Userspace I/O platform driver with dynamic memory.");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
index a879fd5741f8..6a4ba5e83e37 100644
--- a/drivers/uio/uio_netx.c
+++ b/drivers/uio/uio_netx.c
@@ -48,7 +48,7 @@ static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
return IRQ_HANDLED;
}
-static int __devinit netx_pci_probe(struct pci_dev *dev,
+static int netx_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct uio_info *info;
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 0bd08ef2b394..14aa10c1f6de 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -53,7 +53,7 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
return IRQ_HANDLED;
}
-static int __devinit probe(struct pci_dev *pdev,
+static int probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct uio_pci_generic_dev *gdev;
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
index 72d3646c7365..39be9e061700 100644
--- a/drivers/uio/uio_pdrv.c
+++ b/drivers/uio/uio_pdrv.c
@@ -60,6 +60,7 @@ static int uio_pdrv_probe(struct platform_device *pdev)
uiomem->memtype = UIO_MEM_PHYS;
uiomem->addr = r->start;
uiomem->size = resource_size(r);
+ uiomem->name = r->name;
++uiomem;
}
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 42202cd83158..c122bca669b6 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -102,7 +102,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
int ret = -EINVAL;
int i;
- if (!uioinfo) {
+ if (pdev->dev.of_node) {
int irq;
/* alloc uioinfo for one device */
@@ -172,6 +172,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
uiomem->memtype = UIO_MEM_PHYS;
uiomem->addr = r->start;
uiomem->size = resource_size(r);
+ uiomem->name = r->name;
++uiomem;
}
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 33a7a273b453..cce0f78341cc 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -112,7 +112,7 @@ static void pruss_cleanup(struct platform_device *dev,
kfree(gdev);
}
-static int __devinit pruss_probe(struct platform_device *dev)
+static int pruss_probe(struct platform_device *dev)
{
struct uio_info *p;
struct uio_pruss_dev *gdev;
@@ -209,7 +209,7 @@ out_free:
return ret;
}
-static int __devexit pruss_remove(struct platform_device *dev)
+static int pruss_remove(struct platform_device *dev)
{
struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
@@ -220,7 +220,7 @@ static int __devexit pruss_remove(struct platform_device *dev)
static struct platform_driver pruss_driver = {
.probe = pruss_probe,
- .remove = __devexit_p(pruss_remove),
+ .remove = pruss_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
index a187fa14c5c0..81a10a563120 100644
--- a/drivers/uio/uio_sercos3.c
+++ b/drivers/uio/uio_sercos3.c
@@ -116,7 +116,7 @@ static int sercos3_setup_iomem(struct pci_dev *dev, struct uio_info *info,
return 0;
}
-static int __devinit sercos3_pci_probe(struct pci_dev *dev,
+static int sercos3_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct uio_info *info;
@@ -197,7 +197,7 @@ static void sercos3_pci_remove(struct pci_dev *dev)
kfree(info);
}
-static struct pci_device_id sercos3_pci_ids[] __devinitdata = {
+static struct pci_device_id sercos3_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9030,
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a3d54366afcc..92f35abee92d 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
/* Some devices don't handle VPD pages correctly */
sdev->skip_vpd_pages = 1;
+ /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+ sdev->no_report_opcodes = 1;
+
+ /* Do not attempt to use WRITE SAME */
+ sdev->no_write_same = 1;
+
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 99ac2cb08b43..dedaf81d8f36 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1076,7 +1076,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
}
_iov = iov + ret;
size = reg->memory_size - addr + reg->guest_phys_addr;
- _iov->iov_len = min((u64)len, size);
+ _iov->iov_len = min((u64)len - s, size);
_iov->iov_base = (void __user *)(unsigned long)
(reg->userspace_addr + addr - reg->guest_phys_addr);
s += size;
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index df5db99af23d..a1e41d4faa71 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -282,7 +282,7 @@ static const struct attribute_group adp5520_bl_attr_group = {
.attrs = adp5520_bl_attributes,
};
-static int __devinit adp5520_bl_probe(struct platform_device *pdev)
+static int adp5520_bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bl;
@@ -333,7 +333,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit adp5520_bl_remove(struct platform_device *pdev)
+static int adp5520_bl_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
struct adp5520_bl *data = bl_get_data(bl);
@@ -375,7 +375,7 @@ static struct platform_driver adp5520_bl_driver = {
.owner = THIS_MODULE,
},
.probe = adp5520_bl_probe,
- .remove = __devexit_p(adp5520_bl_remove),
+ .remove = adp5520_bl_remove,
.suspend = adp5520_bl_suspend,
.resume = adp5520_bl_resume,
};
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 77d1fdba597f..6bb72c0cb803 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -213,7 +213,7 @@ static int adp8860_led_setup(struct adp8860_led *led)
return ret;
}
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
{
struct adp8860_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -295,7 +295,7 @@ static int __devinit adp8860_led_probe(struct i2c_client *client)
return ret;
}
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
{
struct adp8860_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -310,12 +310,12 @@ static int __devexit adp8860_led_remove(struct i2c_client *client)
return 0;
}
#else
-static int __devinit adp8860_led_probe(struct i2c_client *client)
+static int adp8860_led_probe(struct i2c_client *client)
{
return 0;
}
-static int __devexit adp8860_led_remove(struct i2c_client *client)
+static int adp8860_led_remove(struct i2c_client *client)
{
return 0;
}
@@ -650,7 +650,7 @@ static const struct attribute_group adp8860_bl_attr_group = {
.attrs = adp8860_bl_attributes,
};
-static int __devinit adp8860_probe(struct i2c_client *client,
+static int adp8860_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_device *bl;
@@ -755,7 +755,7 @@ out1:
return ret;
}
-static int __devexit adp8860_remove(struct i2c_client *client)
+static int adp8860_remove(struct i2c_client *client)
{
struct adp8860_bl *data = i2c_get_clientdata(client);
@@ -805,7 +805,7 @@ static struct i2c_driver adp8860_driver = {
.name = KBUILD_MODNAME,
},
.probe = adp8860_probe,
- .remove = __devexit_p(adp8860_remove),
+ .remove = adp8860_remove,
.suspend = adp8860_i2c_suspend,
.resume = adp8860_i2c_resume,
.id_table = adp8860_id,
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index edf7f91c8e61..63c882b8177a 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -235,7 +235,7 @@ static int adp8870_led_setup(struct adp8870_led *led)
return ret;
}
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
{
struct adp8870_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -320,7 +320,7 @@ static int __devinit adp8870_led_probe(struct i2c_client *client)
return ret;
}
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
{
struct adp8870_backlight_platform_data *pdata =
client->dev.platform_data;
@@ -335,12 +335,12 @@ static int __devexit adp8870_led_remove(struct i2c_client *client)
return 0;
}
#else
-static int __devinit adp8870_led_probe(struct i2c_client *client)
+static int adp8870_led_probe(struct i2c_client *client)
{
return 0;
}
-static int __devexit adp8870_led_remove(struct i2c_client *client)
+static int adp8870_led_remove(struct i2c_client *client)
{
return 0;
}
@@ -839,7 +839,7 @@ static const struct attribute_group adp8870_bl_attr_group = {
.attrs = adp8870_bl_attributes,
};
-static int __devinit adp8870_probe(struct i2c_client *client,
+static int adp8870_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_properties props;
@@ -929,7 +929,7 @@ out1:
return ret;
}
-static int __devexit adp8870_remove(struct i2c_client *client)
+static int adp8870_remove(struct i2c_client *client)
{
struct adp8870_bl *data = i2c_get_clientdata(client);
@@ -977,7 +977,7 @@ static struct i2c_driver adp8870_driver = {
.name = KBUILD_MODNAME,
},
.probe = adp8870_probe,
- .remove = __devexit_p(adp8870_remove),
+ .remove = adp8870_remove,
.suspend = adp8870_i2c_suspend,
.resume = adp8870_i2c_resume,
.id_table = adp8870_id,
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index 3729238e7096..f57e1905236a 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -474,7 +474,7 @@ static const struct backlight_ops ams369fg06_backlight_ops = {
.update_status = ams369fg06_set_brightness,
};
-static int __devinit ams369fg06_probe(struct spi_device *spi)
+static int ams369fg06_probe(struct spi_device *spi)
{
int ret = 0;
struct ams369fg06 *lcd = NULL;
@@ -548,7 +548,7 @@ out_lcd_unregister:
return ret;
}
-static int __devexit ams369fg06_remove(struct spi_device *spi)
+static int ams369fg06_remove(struct spi_device *spi)
{
struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev);
@@ -617,7 +617,7 @@ static struct spi_driver ams369fg06_driver = {
.owner = THIS_MODULE,
},
.probe = ams369fg06_probe,
- .remove = __devexit_p(ams369fg06_remove),
+ .remove = ams369fg06_remove,
.shutdown = ams369fg06_shutdown,
.suspend = ams369fg06_suspend,
.resume = ams369fg06_resume,
diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
index 9dc73ac3709a..f088d4c07381 100644
--- a/drivers/video/backlight/apple_bl.c
+++ b/drivers/video/backlight/apple_bl.c
@@ -137,7 +137,7 @@ static const struct hw_data nvidia_chipset_data = {
.set_brightness = nvidia_chipset_set_brightness,
};
-static int __devinit apple_bl_add(struct acpi_device *dev)
+static int apple_bl_add(struct acpi_device *dev)
{
struct backlight_properties props;
struct pci_dev *host;
@@ -196,7 +196,7 @@ static int __devinit apple_bl_add(struct acpi_device *dev)
return 0;
}
-static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
+static int apple_bl_remove(struct acpi_device *dev, int type)
{
backlight_device_unregister(apple_backlight_device);
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index c781768ba892..eaaebf21993e 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -529,7 +529,7 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd,
return 0;
}
-static int __devinit corgi_lcd_probe(struct spi_device *spi)
+static int corgi_lcd_probe(struct spi_device *spi)
{
struct backlight_properties props;
struct corgi_lcd_platform_data *pdata = spi->dev.platform_data;
@@ -590,7 +590,7 @@ err_unregister_lcd:
return ret;
}
-static int __devexit corgi_lcd_remove(struct spi_device *spi)
+static int corgi_lcd_remove(struct spi_device *spi)
{
struct corgi_lcd *lcd = dev_get_drvdata(&spi->dev);
@@ -611,7 +611,7 @@ static struct spi_driver corgi_lcd_driver = {
.owner = THIS_MODULE,
},
.probe = corgi_lcd_probe,
- .remove = __devexit_p(corgi_lcd_remove),
+ .remove = corgi_lcd_remove,
.suspend = corgi_lcd_suspend,
.resume = corgi_lcd_resume,
};
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index 08214e1f0958..ef3e21e8f825 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -141,7 +141,7 @@ static struct platform_driver ep93xxbl_driver = {
.owner = THIS_MODULE,
},
.probe = ep93xxbl_probe,
- .remove = __devexit_p(ep93xxbl_remove),
+ .remove = ep93xxbl_remove,
.suspend = ep93xxbl_suspend,
.resume = ep93xxbl_resume,
};
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 38aa00272141..c99966342448 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -103,7 +103,7 @@ static const struct backlight_ops hp680bl_ops = {
.update_status = hp680bl_set_intensity,
};
-static int __devinit hp680bl_probe(struct platform_device *pdev)
+static int hp680bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bd;
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c
index 9327cd1b3143..66cc313185ad 100644
--- a/drivers/video/backlight/ili9320.c
+++ b/drivers/video/backlight/ili9320.c
@@ -171,7 +171,7 @@ static struct lcd_ops ili9320_ops = {
.set_power = ili9320_set_power,
};
-static void __devinit ili9320_setup_spi(struct ili9320 *ili,
+static void ili9320_setup_spi(struct ili9320 *ili,
struct spi_device *dev)
{
struct ili9320_spi *spi = &ili->access.spi;
@@ -197,7 +197,7 @@ static void __devinit ili9320_setup_spi(struct ili9320 *ili,
spi_message_add_tail(&spi->xfer[1], &spi->message);
}
-int __devinit ili9320_probe_spi(struct spi_device *spi,
+int ili9320_probe_spi(struct spi_device *spi,
struct ili9320_client *client)
{
struct ili9320_platdata *cfg = spi->dev.platform_data;
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 2d90c0648aa0..f5aa0a5961d6 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -150,7 +150,7 @@ static struct lcd_ops l4f_ops = {
.get_power = l4f00242t03_lcd_power_get,
};
-static int __devinit l4f00242t03_probe(struct spi_device *spi)
+static int l4f00242t03_probe(struct spi_device *spi)
{
struct l4f00242t03_priv *priv;
struct l4f00242t03_pdata *pdata = spi->dev.platform_data;
@@ -230,7 +230,7 @@ err1:
return ret;
}
-static int __devexit l4f00242t03_remove(struct spi_device *spi)
+static int l4f00242t03_remove(struct spi_device *spi)
{
struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev);
@@ -260,7 +260,7 @@ static struct spi_driver l4f00242t03_driver = {
.owner = THIS_MODULE,
},
.probe = l4f00242t03_probe,
- .remove = __devexit_p(l4f00242t03_remove),
+ .remove = l4f00242t03_remove,
.shutdown = l4f00242t03_shutdown,
};
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 58f517fb7d40..1cb352418513 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -788,7 +788,7 @@ out_free_regulator:
return ret;
}
-static int __devexit ld9040_remove(struct spi_device *spi)
+static int ld9040_remove(struct spi_device *spi)
{
struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
@@ -847,7 +847,7 @@ static struct spi_driver ld9040_driver = {
.owner = THIS_MODULE,
},
.probe = ld9040_probe,
- .remove = __devexit_p(ld9040_remove),
+ .remove = ld9040_remove,
.shutdown = ld9040_shutdown,
.suspend = ld9040_suspend,
.resume = ld9040_resume,
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 18dca0c29c68..5d18d4d7f470 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -257,7 +257,7 @@ static struct attribute_group lm3533_bl_attribute_group = {
.attrs = lm3533_bl_attributes
};
-static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
+static int lm3533_bl_setup(struct lm3533_bl *bl,
struct lm3533_bl_platform_data *pdata)
{
int ret;
@@ -269,7 +269,7 @@ static int __devinit lm3533_bl_setup(struct lm3533_bl *bl,
return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
}
-static int __devinit lm3533_bl_probe(struct platform_device *pdev)
+static int lm3533_bl_probe(struct platform_device *pdev)
{
struct lm3533 *lm3533;
struct lm3533_bl_platform_data *pdata;
@@ -351,7 +351,7 @@ err_unregister:
return ret;
}
-static int __devexit lm3533_bl_remove(struct platform_device *pdev)
+static int lm3533_bl_remove(struct platform_device *pdev)
{
struct lm3533_bl *bl = platform_get_drvdata(pdev);
struct backlight_device *bd = bl->bd;
@@ -406,7 +406,7 @@ static struct platform_driver lm3533_bl_driver = {
.owner = THIS_MODULE,
},
.probe = lm3533_bl_probe,
- .remove = __devexit_p(lm3533_bl_remove),
+ .remove = lm3533_bl_remove,
.shutdown = lm3533_bl_shutdown,
.suspend = lm3533_bl_suspend,
.resume = lm3533_bl_resume,
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c
index dc191441796f..0207bc0a4407 100644
--- a/drivers/video/backlight/lm3630_bl.c
+++ b/drivers/video/backlight/lm3630_bl.c
@@ -55,7 +55,7 @@ struct lm3630_chip_data {
};
/* initialize chip */
-static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip)
+static int lm3630_chip_init(struct lm3630_chip_data *pchip)
{
int ret;
unsigned int reg_val;
@@ -349,7 +349,7 @@ static const struct regmap_config lm3630_regmap = {
.max_register = REG_MAX,
};
-static int __devinit lm3630_probe(struct i2c_client *client,
+static int lm3630_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm3630_platform_data *pdata = client->dev.platform_data;
@@ -429,7 +429,7 @@ err_chip_init:
return ret;
}
-static int __devexit lm3630_remove(struct i2c_client *client)
+static int lm3630_remove(struct i2c_client *client)
{
int ret;
struct lm3630_chip_data *pchip = i2c_get_clientdata(client);
@@ -463,7 +463,7 @@ static struct i2c_driver lm3630_i2c_driver = {
.name = LM3630_NAME,
},
.probe = lm3630_probe,
- .remove = __devexit_p(lm3630_remove),
+ .remove = lm3630_remove,
.id_table = lm3630_id,
};
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
index 585949b57055..b0e1e8ba4d9f 100644
--- a/drivers/video/backlight/lm3639_bl.c
+++ b/drivers/video/backlight/lm3639_bl.c
@@ -48,7 +48,7 @@ struct lm3639_chip_data {
};
/* initialize chip */
-static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip)
+static int lm3639_chip_init(struct lm3639_chip_data *pchip)
{
int ret;
unsigned int reg_val;
@@ -299,7 +299,7 @@ static const struct regmap_config lm3639_regmap = {
.max_register = REG_MAX,
};
-static int __devinit lm3639_probe(struct i2c_client *client,
+static int lm3639_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
@@ -397,7 +397,7 @@ err_out:
return ret;
}
-static int __devexit lm3639_remove(struct i2c_client *client)
+static int lm3639_remove(struct i2c_client *client)
{
struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
@@ -425,7 +425,7 @@ static struct i2c_driver lm3639_i2c_driver = {
.name = LM3639_NAME,
},
.probe = lm3639_probe,
- .remove = __devexit_p(lm3639_remove),
+ .remove = lm3639_remove,
.id_table = lm3639_id,
};
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index ea43f2254196..b29c7071c9db 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -150,7 +150,7 @@ static struct lcd_ops lms_ops = {
.get_power = NULL,
};
-static int __devinit lms283gf05_probe(struct spi_device *spi)
+static int lms283gf05_probe(struct spi_device *spi)
{
struct lms283gf05_state *st;
struct lms283gf05_pdata *pdata = spi->dev.platform_data;
@@ -193,7 +193,7 @@ static int __devinit lms283gf05_probe(struct spi_device *spi)
return 0;
}
-static int __devexit lms283gf05_remove(struct spi_device *spi)
+static int lms283gf05_remove(struct spi_device *spi)
{
struct lms283gf05_state *st = dev_get_drvdata(&spi->dev);
@@ -208,7 +208,7 @@ static struct spi_driver lms283gf05_driver = {
.owner = THIS_MODULE,
},
.probe = lms283gf05_probe,
- .remove = __devexit_p(lms283gf05_remove),
+ .remove = lms283gf05_remove,
};
module_spi_driver(lms283gf05_driver);
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index aa6d4f71131f..fd985e0681e9 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -297,7 +297,7 @@ err_dev:
return ret;
}
-static int __devexit lp855x_remove(struct i2c_client *cl)
+static int lp855x_remove(struct i2c_client *cl)
{
struct lp855x *lp = i2c_get_clientdata(cl);
@@ -324,7 +324,7 @@ static struct i2c_driver lp855x_driver = {
.name = "lp855x",
},
.probe = lp855x_probe,
- .remove = __devexit_p(lp855x_remove),
+ .remove = lp855x_remove,
.id_table = lp855x_ids,
};
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index 4066a5bbd826..226d813edf01 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -226,7 +226,7 @@ static struct lcd_ops ltv_ops = {
.set_power = ltv350qv_set_power,
};
-static int __devinit ltv350qv_probe(struct spi_device *spi)
+static int ltv350qv_probe(struct spi_device *spi)
{
struct ltv350qv *lcd;
struct lcd_device *ld;
@@ -261,7 +261,7 @@ out_unregister:
return ret;
}
-static int __devexit ltv350qv_remove(struct spi_device *spi)
+static int ltv350qv_remove(struct spi_device *spi)
{
struct ltv350qv *lcd = dev_get_drvdata(&spi->dev);
@@ -305,7 +305,7 @@ static struct spi_driver ltv350qv_driver = {
},
.probe = ltv350qv_probe,
- .remove = __devexit_p(ltv350qv_remove),
+ .remove = ltv350qv_remove,
.shutdown = ltv350qv_shutdown,
.suspend = ltv350qv_suspend,
.resume = ltv350qv_resume,
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index f72ba54f364e..c6bec7aab87b 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -101,7 +101,7 @@ static const struct backlight_ops max8925_backlight_ops = {
.get_brightness = max8925_backlight_get_brightness,
};
-static int __devinit max8925_backlight_probe(struct platform_device *pdev)
+static int max8925_backlight_probe(struct platform_device *pdev)
{
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct max8925_backlight_pdata *pdata = pdev->dev.platform_data;
@@ -171,7 +171,7 @@ out:
return ret;
}
-static int __devexit max8925_backlight_remove(struct platform_device *pdev)
+static int max8925_backlight_remove(struct platform_device *pdev)
{
struct backlight_device *bl = platform_get_drvdata(pdev);
@@ -185,7 +185,7 @@ static struct platform_driver max8925_backlight_driver = {
.owner = THIS_MODULE,
},
.probe = max8925_backlight_probe,
- .remove = __devexit_p(max8925_backlight_remove),
+ .remove = max8925_backlight_remove,
};
module_platform_driver(max8925_backlight_driver);
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index c092159f4383..0087396007e4 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -99,7 +99,7 @@ static const struct backlight_ops pcf50633_bl_ops = {
.options = BL_CORE_SUSPENDRESUME,
};
-static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
+static int pcf50633_bl_probe(struct platform_device *pdev)
{
struct pcf50633_bl *pcf_bl;
struct device *parent = pdev->dev.parent;
@@ -145,7 +145,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
+static int pcf50633_bl_remove(struct platform_device *pdev)
{
struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev);
@@ -158,7 +158,7 @@ static int __devexit pcf50633_bl_remove(struct platform_device *pdev)
static struct platform_driver pcf50633_bl_driver = {
.probe = pcf50633_bl_probe,
- .remove = __devexit_p(pcf50633_bl_remove),
+ .remove = pcf50633_bl_remove,
.driver = {
.name = "pcf50633-backlight",
},
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index ca4f5d70fe10..894bfc5ce422 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -73,7 +73,7 @@ static struct lcd_ops platform_lcd_ops = {
.check_fb = platform_lcd_match,
};
-static int __devinit platform_lcd_probe(struct platform_device *pdev)
+static int platform_lcd_probe(struct platform_device *pdev)
{
struct plat_lcd_data *pdata;
struct platform_lcd *plcd;
@@ -112,7 +112,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev)
return err;
}
-static int __devexit platform_lcd_remove(struct platform_device *pdev)
+static int platform_lcd_remove(struct platform_device *pdev)
{
struct platform_lcd *plcd = platform_get_drvdata(pdev);
@@ -164,7 +164,7 @@ static struct platform_driver platform_lcd_driver = {
.of_match_table = of_match_ptr(platform_lcd_of_match),
},
.probe = platform_lcd_probe,
- .remove = __devexit_p(platform_lcd_remove),
+ .remove = platform_lcd_remove,
};
module_platform_driver(platform_lcd_driver);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 6437ae474cf2..484e10dd1a8e 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -733,7 +733,7 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev,
static DEVICE_ATTR(gamma_table, 0444,
s6e63m0_sysfs_show_gamma_table, NULL);
-static int __devinit s6e63m0_probe(struct spi_device *spi)
+static int s6e63m0_probe(struct spi_device *spi)
{
int ret = 0;
struct s6e63m0 *lcd = NULL;
@@ -825,7 +825,7 @@ out_lcd_unregister:
return ret;
}
-static int __devexit s6e63m0_remove(struct spi_device *spi)
+static int s6e63m0_remove(struct spi_device *spi)
{
struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev);
@@ -897,7 +897,7 @@ static struct spi_driver s6e63m0_driver = {
.owner = THIS_MODULE,
},
.probe = s6e63m0_probe,
- .remove = __devexit_p(s6e63m0_remove),
+ .remove = s6e63m0_remove,
.shutdown = s6e63m0_shutdown,
.suspend = s6e63m0_suspend,
.resume = s6e63m0_resume,
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 02444d042cd5..146ffb9404d1 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -328,7 +328,7 @@ static struct lcd_ops tdo24m_ops = {
.set_mode = tdo24m_set_mode,
};
-static int __devinit tdo24m_probe(struct spi_device *spi)
+static int tdo24m_probe(struct spi_device *spi)
{
struct tdo24m *lcd;
struct spi_message *m;
@@ -401,7 +401,7 @@ out_unregister:
return err;
}
-static int __devexit tdo24m_remove(struct spi_device *spi)
+static int tdo24m_remove(struct spi_device *spi)
{
struct tdo24m *lcd = dev_get_drvdata(&spi->dev);
@@ -444,7 +444,7 @@ static struct spi_driver tdo24m_driver = {
.owner = THIS_MODULE,
},
.probe = tdo24m_probe,
- .remove = __devexit_p(tdo24m_remove),
+ .remove = tdo24m_remove,
.shutdown = tdo24m_shutdown,
.suspend = tdo24m_suspend,
.resume = tdo24m_resume,
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 49342e1d20be..a0521abdcd8a 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -78,7 +78,7 @@ static const struct backlight_ops bl_ops = {
.update_status = tosa_bl_update_status,
};
-static int __devinit tosa_bl_probe(struct i2c_client *client,
+static int tosa_bl_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct backlight_properties props;
@@ -126,7 +126,7 @@ err_reg:
return ret;
}
-static int __devexit tosa_bl_remove(struct i2c_client *client)
+static int tosa_bl_remove(struct i2c_client *client)
{
struct tosa_bl_data *data = i2c_get_clientdata(client);
@@ -170,7 +170,7 @@ static struct i2c_driver tosa_bl_driver = {
.owner = THIS_MODULE,
},
.probe = tosa_bl_probe,
- .remove = __devexit_p(tosa_bl_remove),
+ .remove = tosa_bl_remove,
.suspend = tosa_bl_suspend,
.resume = tosa_bl_resume,
.id_table = tosa_bl_id,
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 33047a66cc24..86fff88c2e4a 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -169,7 +169,7 @@ static struct lcd_ops tosa_lcd_ops = {
.set_mode = tosa_lcd_set_mode,
};
-static int __devinit tosa_lcd_probe(struct spi_device *spi)
+static int tosa_lcd_probe(struct spi_device *spi)
{
int ret;
struct tosa_lcd_data *data;
@@ -226,7 +226,7 @@ err_gpio_tg:
return ret;
}
-static int __devexit tosa_lcd_remove(struct spi_device *spi)
+static int tosa_lcd_remove(struct spi_device *spi)
{
struct tosa_lcd_data *data = dev_get_drvdata(&spi->dev);
@@ -275,7 +275,7 @@ static struct spi_driver tosa_lcd_driver = {
.owner = THIS_MODULE,
},
.probe = tosa_lcd_probe,
- .remove = __devexit_p(tosa_lcd_remove),
+ .remove = tosa_lcd_remove,
.suspend = tosa_lcd_suspend,
.resume = tosa_lcd_resume,
};
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index b617fae9aa26..712b0acfd339 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -227,7 +227,7 @@ static struct ili9320_client vgg2432a4_client = {
/* Device probe */
-static int __devinit vgg2432a4_probe(struct spi_device *spi)
+static int vgg2432a4_probe(struct spi_device *spi)
{
int ret;
@@ -240,7 +240,7 @@ static int __devinit vgg2432a4_probe(struct spi_device *spi)
return 0;
}
-static int __devexit vgg2432a4_remove(struct spi_device *spi)
+static int vgg2432a4_remove(struct spi_device *spi)
{
return ili9320_remove(dev_get_drvdata(&spi->dev));
}
@@ -256,7 +256,7 @@ static struct spi_driver vgg2432a4_driver = {
.owner = THIS_MODULE,
},
.probe = vgg2432a4_probe,
- .remove = __devexit_p(vgg2432a4_remove),
+ .remove = vgg2432a4_remove,
.shutdown = vgg2432a4_shutdown,
.suspend = vgg2432a4_suspend,
.resume = vgg2432a4_resume,
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index d64ac3842884..bee92846cfab 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
struct omap_dss_output *out;
enum omap_dss_output_id id;
- id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+ switch (module) {
+ case 0:
+ id = OMAP_DSS_OUTPUT_DSI1;
+ break;
+ case 1:
+ id = OMAP_DSS_OUTPUT_DSI2;
+ break;
+ default:
+ return NULL;
+ }
out = omap_dss_get_output(id);
- return out->pdev;
+ return out ? out->pdev : NULL;
}
static inline void dsi_write_reg(struct platform_device *dsidev,
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 2ab1c3e96553..5f6eea801b06 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -697,11 +697,15 @@ static int dss_get_clocks(void)
dss.dss_clk = clk;
- clk = clk_get(NULL, dss.feat->clk_name);
- if (IS_ERR(clk)) {
- DSSERR("Failed to get %s\n", dss.feat->clk_name);
- r = PTR_ERR(clk);
- goto err;
+ if (dss.feat->clk_name) {
+ clk = clk_get(NULL, dss.feat->clk_name);
+ if (IS_ERR(clk)) {
+ DSSERR("Failed to get %s\n", dss.feat->clk_name);
+ r = PTR_ERR(clk);
+ goto err;
+ }
+ } else {
+ clk = NULL;
}
dss.dpll4_m4_ck = clk;
@@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev)
if (cpu_is_omap24xx())
src = &omap24xx_dss_feats;
- else if (cpu_is_omap34xx())
- src = &omap34xx_dss_feats;
else if (cpu_is_omap3630())
src = &omap3630_dss_feats;
+ else if (cpu_is_omap34xx())
+ src = &omap34xx_dss_feats;
else if (cpu_is_omap44xx())
src = &omap44xx_dss_feats;
else if (soc_is_omap54xx())
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index a48a7dd75b33..8c9b8b3b7f77 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s)
{
mutex_lock(&hdmi.lock);
- if (hdmi_runtime_get())
+ if (hdmi_runtime_get()) {
+ mutex_unlock(&hdmi.lock);
return;
+ }
hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 606b89f12351..d630b26a005c 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
case OMAPFB_WAITFORVSYNC:
DBG("ioctl WAITFORVSYNC\n");
- if (!display && !display->output && !display->output->manager) {
+ if (!display || !display->output || !display->output->manager) {
r = -EINVAL;
break;
}
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 7e984034a11b..c433a746e3f5 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -26,7 +26,7 @@ config W1_MASTER_DS2490
config W1_MASTER_DS2482
tristate "Maxim DS2482 I2C to 1-Wire bridge"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
help
If you say yes here you get support for the Maxim DS2482
I2C to 1-Wire bridge.
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index e5f74416d4b7..6429b9e9fb82 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -505,19 +505,8 @@ static int ds2482_remove(struct i2c_client *client)
return 0;
}
-static int __init sensors_ds2482_init(void)
-{
- return i2c_add_driver(&ds2482_driver);
-}
-
-static void __exit sensors_ds2482_exit(void)
-{
- i2c_del_driver(&ds2482_driver);
-}
+module_i2c_driver(ds2482_driver);
MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
MODULE_DESCRIPTION("DS2482 driver");
MODULE_LICENSE("GPL");
-
-module_init(sensors_ds2482_init);
-module_exit(sensors_ds2482_exit);
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index f667c26b2195..d8667b0212d7 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -48,14 +48,14 @@ static struct pci_device_id matrox_w1_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
-static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit matrox_w1_remove(struct pci_dev *);
+static int matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+static void matrox_w1_remove(struct pci_dev *);
static struct pci_driver matrox_w1_pci_driver = {
.name = "matrox_w1",
.id_table = matrox_w1_tbl,
.probe = matrox_w1_probe,
- .remove = __devexit_p(matrox_w1_remove),
+ .remove = matrox_w1_remove,
};
/*
@@ -152,7 +152,7 @@ static void matrox_w1_hw_init(struct matrox_device *dev)
matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
}
-static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct matrox_device *dev;
int err;
@@ -220,7 +220,7 @@ err_out_free_device:
return err;
}
-static void __devexit matrox_w1_remove(struct pci_dev *pdev)
+static void matrox_w1_remove(struct pci_dev *pdev)
{
struct matrox_device *dev = pci_get_drvdata(pdev);
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 1cc61a700fa8..d338b56ea2f0 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -103,7 +103,7 @@ static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit)
return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
}
-static int __devinit mxc_w1_probe(struct platform_device *pdev)
+static int mxc_w1_probe(struct platform_device *pdev)
{
struct mxc_w1_device *mdev;
struct resource *res;
@@ -117,9 +117,9 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev)
if (!mdev)
return -ENOMEM;
- mdev->clk = clk_get(&pdev->dev, "owire");
- if (!mdev->clk) {
- err = -ENODEV;
+ mdev->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(mdev->clk)) {
+ err = PTR_ERR(mdev->clk);
goto failed_clk;
}
@@ -134,7 +134,7 @@ static int __devinit mxc_w1_probe(struct platform_device *pdev)
mdev->regs = ioremap(res->start, resource_size(res));
if (!mdev->regs) {
- printk(KERN_ERR "Cannot map frame buffer registers\n");
+ dev_err(&pdev->dev, "Cannot map mxc_w1 registers\n");
goto failed_ioremap;
}
@@ -167,7 +167,7 @@ failed_clk:
/*
* disassociate the w1 device from the driver
*/
-static int __devexit mxc_w1_remove(struct platform_device *pdev)
+static int mxc_w1_remove(struct platform_device *pdev)
{
struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
struct resource *res;
@@ -191,21 +191,9 @@ static struct platform_driver mxc_w1_driver = {
.name = "mxc_w1",
},
.probe = mxc_w1_probe,
- .remove = mxc_w1_remove,
+ .remove = __devexit_p(mxc_w1_remove),
};
-
-static int __init mxc_w1_init(void)
-{
- return platform_driver_register(&mxc_w1_driver);
-}
-
-static void mxc_w1_exit(void)
-{
- platform_driver_unregister(&mxc_w1_driver);
-}
-
-module_init(mxc_w1_init);
-module_exit(mxc_w1_exit);
+module_platform_driver(mxc_w1_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Freescale Semiconductors Inc");
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index ca8e60bb2f9c..184dbce4abd1 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -69,12 +69,12 @@ struct hdq_data {
int init_trans;
};
-static int __devinit omap_hdq_probe(struct platform_device *pdev);
-static int __devexit omap_hdq_remove(struct platform_device *pdev);
+static int omap_hdq_probe(struct platform_device *pdev);
+static int omap_hdq_remove(struct platform_device *pdev);
static struct platform_driver omap_hdq_driver = {
.probe = omap_hdq_probe,
- .remove = __devexit_p(omap_hdq_remove),
+ .remove = omap_hdq_remove,
.driver = {
.name = "omap_hdq",
},
@@ -537,7 +537,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
}
}
-static int __devinit omap_hdq_probe(struct platform_device *pdev)
+static int omap_hdq_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct hdq_data *hdq_data;
@@ -613,7 +613,7 @@ err_w1:
return ret;
}
-static int __devexit omap_hdq_remove(struct platform_device *pdev)
+static int omap_hdq_remove(struct platform_device *pdev)
{
struct hdq_data *hdq_data = platform_get_drvdata(pdev);
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 6012c4ea3206..85b363a5bd0f 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -16,6 +16,9 @@
#include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <linux/of.h>
#include "../w1.h"
#include "../w1_int.h"
@@ -44,7 +47,6 @@ static u8 w1_gpio_read_bit(void *data)
return gpio_get_value(pdata->pin) ? 1 : 0;
}
-#ifdef CONFIG_OF
static struct of_device_id w1_gpio_dt_ids[] = {
{ .compatible = "w1-gpio" },
{}
@@ -55,11 +57,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
{
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *of_id =
- of_match_device(w1_gpio_dt_ids, &pdev->dev);
-
- if (!of_id)
- return 0;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -74,41 +71,53 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
return 0;
}
-#else
-static int w1_gpio_probe_dt(struct platform_device *pdev)
-{
- return 0;
-}
-#endif
static int __init w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata;
+ struct pinctrl *pinctrl;
int err;
- err = w1_gpio_probe_dt(pdev);
- if (err < 0)
- return err;
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+
+ if (of_have_populated_dt()) {
+ err = w1_gpio_probe_dt(pdev);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Failed to parse DT\n");
+ return err;
+ }
+ }
pdata = pdev->dev.platform_data;
- if (!pdata)
+ if (!pdata) {
+ dev_err(&pdev->dev, "No configuration data\n");
return -ENXIO;
+ }
master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
- if (!master)
+ if (!master) {
+ dev_err(&pdev->dev, "Out of memory\n");
return -ENOMEM;
+ }
err = gpio_request(pdata->pin, "w1");
- if (err)
+ if (err) {
+ dev_err(&pdev->dev, "gpio_request (pin) failed\n");
goto free_master;
+ }
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
err = gpio_request_one(pdata->ext_pullup_enable_pin,
GPIOF_INIT_LOW, "w1 pullup");
- if (err < 0)
+ if (err < 0) {
+ dev_err(&pdev->dev, "gpio_request_one "
+ "(ext_pullup_enable_pin) failed\n");
goto free_gpio;
+ }
}
master->data = pdata;
@@ -123,8 +132,10 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
}
err = w1_add_master_device(master);
- if (err)
+ if (err) {
+ dev_err(&pdev->dev, "w1_add_master device failed\n");
goto free_gpio_ext_pu;
+ }
if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1);
@@ -198,23 +209,13 @@ static struct platform_driver w1_gpio_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(w1_gpio_dt_ids),
},
+ .probe = w1_gpio_probe,
.remove = __exit_p(w1_gpio_remove),
.suspend = w1_gpio_suspend,
.resume = w1_gpio_resume,
};
-static int __init w1_gpio_init(void)
-{
- return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
-}
-
-static void __exit w1_gpio_exit(void)
-{
- platform_driver_unregister(&w1_gpio_driver);
-}
-
-module_init(w1_gpio_init);
-module_exit(w1_gpio_exit);
+module_platform_driver(w1_gpio_driver);
MODULE_DESCRIPTION("GPIO w1 bus master driver");
MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 1a574370d2cd..7994d933f040 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -551,7 +551,6 @@ void w1_destroy_master_attributes(struct w1_master *master)
sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}
-#ifdef CONFIG_HOTPLUG
static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct w1_master *md = NULL;
@@ -587,12 +586,6 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
end:
return err;
}
-#else
-static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- return 0;
-}
-#endif
static int __w1_attach_slave_device(struct w1_slave *sl)
{
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 4397881c83f4..24a517777fa0 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -240,7 +240,7 @@ static struct miscdevice acq_miscdev = {
* Init & exit routines
*/
-static int __devinit acq_probe(struct platform_device *dev)
+static int acq_probe(struct platform_device *dev)
{
int ret;
@@ -275,7 +275,7 @@ out:
return ret;
}
-static int __devexit acq_remove(struct platform_device *dev)
+static int acq_remove(struct platform_device *dev)
{
misc_deregister(&acq_miscdev);
release_region(wdt_start, 1);
@@ -293,7 +293,7 @@ static void acq_shutdown(struct platform_device *dev)
static struct platform_driver acquirewdt_driver = {
.probe = acq_probe,
- .remove = __devexit_p(acq_remove),
+ .remove = acq_remove,
.shutdown = acq_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 64ae9e9fed94..cc6702fc5268 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -238,7 +238,7 @@ static struct miscdevice advwdt_miscdev = {
* Init & exit routines
*/
-static int __devinit advwdt_probe(struct platform_device *dev)
+static int advwdt_probe(struct platform_device *dev)
{
int ret;
@@ -282,7 +282,7 @@ unreg_stop:
goto out;
}
-static int __devexit advwdt_remove(struct platform_device *dev)
+static int advwdt_remove(struct platform_device *dev)
{
misc_deregister(&advwdt_miscdev);
release_region(wdt_start, 1);
@@ -300,7 +300,7 @@ static void advwdt_shutdown(struct platform_device *dev)
static struct platform_driver advwdt_driver = {
.probe = advwdt_probe,
- .remove = __devexit_p(advwdt_remove),
+ .remove = advwdt_remove,
.shutdown = advwdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index dc30dbd21cf1..3003e2a9580b 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -274,7 +274,7 @@ static struct miscdevice ar7_wdt_miscdev = {
.fops = &ar7_wdt_fops,
};
-static int __devinit ar7_wdt_probe(struct platform_device *pdev)
+static int ar7_wdt_probe(struct platform_device *pdev)
{
int rc;
@@ -314,7 +314,7 @@ out:
return rc;
}
-static int __devexit ar7_wdt_remove(struct platform_device *pdev)
+static int ar7_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&ar7_wdt_miscdev);
clk_put(vbus_clk);
@@ -330,7 +330,7 @@ static void ar7_wdt_shutdown(struct platform_device *pdev)
static struct platform_driver ar7_wdt_driver = {
.probe = ar7_wdt_probe,
- .remove = __devexit_p(ar7_wdt_remove),
+ .remove = ar7_wdt_remove,
.shutdown = ar7_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 7ef99a169e3b..89831ed24a4f 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -199,7 +199,7 @@ static struct miscdevice at91wdt_miscdev = {
.fops = &at91wdt_fops,
};
-static int __devinit at91wdt_probe(struct platform_device *pdev)
+static int at91wdt_probe(struct platform_device *pdev)
{
int res;
@@ -216,7 +216,7 @@ static int __devinit at91wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit at91wdt_remove(struct platform_device *pdev)
+static int at91wdt_remove(struct platform_device *pdev)
{
int res;
@@ -254,7 +254,7 @@ static int at91wdt_resume(struct platform_device *pdev)
static struct platform_driver at91wdt_driver = {
.probe = at91wdt_probe,
- .remove = __devexit_p(at91wdt_remove),
+ .remove = at91wdt_remove,
.shutdown = at91wdt_shutdown,
.suspend = at91wdt_suspend,
.resume = at91wdt_resume,
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index 1f9371f49c40..7c8ede7816b1 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -224,7 +224,7 @@ static struct miscdevice ath79_wdt_miscdev = {
.fops = &ath79_wdt_fops,
};
-static int __devinit ath79_wdt_probe(struct platform_device *pdev)
+static int ath79_wdt_probe(struct platform_device *pdev)
{
u32 ctrl;
int err;
@@ -270,7 +270,7 @@ err_clk_put:
return err;
}
-static int __devexit ath79_wdt_remove(struct platform_device *pdev)
+static int ath79_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&ath79_wdt_miscdev);
clk_disable(wdt_clk);
@@ -284,7 +284,7 @@ static void ath97_wdt_shutdown(struct platform_device *pdev)
}
static struct platform_driver ath79_wdt_driver = {
- .remove = __devexit_p(ath79_wdt_remove),
+ .remove = ath79_wdt_remove,
.shutdown = ath97_wdt_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 551880bfd629..b2b80d4ac818 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -236,7 +236,7 @@ static struct miscdevice bcm63xx_wdt_miscdev = {
};
-static int __devinit bcm63xx_wdt_probe(struct platform_device *pdev)
+static int bcm63xx_wdt_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
@@ -286,7 +286,7 @@ unmap:
return ret;
}
-static int __devexit bcm63xx_wdt_remove(struct platform_device *pdev)
+static int bcm63xx_wdt_remove(struct platform_device *pdev)
{
if (!nowayout)
bcm63xx_wdt_pause();
@@ -304,7 +304,7 @@ static void bcm63xx_wdt_shutdown(struct platform_device *pdev)
static struct platform_driver bcm63xx_wdt_driver = {
.probe = bcm63xx_wdt_probe,
- .remove = __devexit_p(bcm63xx_wdt_remove),
+ .remove = bcm63xx_wdt_remove,
.shutdown = bcm63xx_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 38bc383e0677..5d36d6fb4969 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -356,7 +356,7 @@ static const struct watchdog_info bfin_wdt_info = {
* Registers the misc device. Actual device
* initialization is handled by bfin_wdt_open().
*/
-static int __devinit bfin_wdt_probe(struct platform_device *pdev)
+static int bfin_wdt_probe(struct platform_device *pdev)
{
int ret;
@@ -379,7 +379,7 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
* Unregisters the misc device. Actual device
* deinitialization is handled by bfin_wdt_close().
*/
-static int __devexit bfin_wdt_remove(struct platform_device *pdev)
+static int bfin_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&bfin_wdt_miscdev);
return 0;
@@ -401,7 +401,7 @@ static struct platform_device *bfin_wdt_device;
static struct platform_driver bfin_wdt_driver = {
.probe = bfin_wdt_probe,
- .remove = __devexit_p(bfin_wdt_remove),
+ .remove = bfin_wdt_remove,
.shutdown = bfin_wdt_shutdown,
.suspend = bfin_wdt_suspend,
.resume = bfin_wdt_resume,
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 7e888393de1f..cd87758abac3 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -215,7 +215,7 @@ static struct miscdevice cpu5wdt_misc = {
/* init/exit function */
-static int __devinit cpu5wdt_init(void)
+static int cpu5wdt_init(void)
{
unsigned int val;
int err;
@@ -256,12 +256,12 @@ no_port:
return err;
}
-static int __devinit cpu5wdt_init_module(void)
+static int cpu5wdt_init_module(void)
{
return cpu5wdt_init();
}
-static void __devexit cpu5wdt_exit(void)
+static void cpu5wdt_exit(void)
{
if (cpu5wdt_device.queue) {
cpu5wdt_device.queue = 0;
@@ -274,7 +274,7 @@ static void __devexit cpu5wdt_exit(void)
}
-static void __devexit cpu5wdt_exit_module(void)
+static void cpu5wdt_exit_module(void)
{
cpu5wdt_exit();
}
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 95b1b954de1b..11d55ce5ca81 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -528,7 +528,7 @@ static const struct file_operations cpwd_fops = {
.llseek = no_llseek,
};
-static int __devinit cpwd_probe(struct platform_device *op)
+static int cpwd_probe(struct platform_device *op)
{
struct device_node *options;
const char *str_prop;
@@ -640,7 +640,7 @@ out_free:
goto out;
}
-static int __devexit cpwd_remove(struct platform_device *op)
+static int cpwd_remove(struct platform_device *op)
{
struct cpwd *p = dev_get_drvdata(&op->dev);
int i;
@@ -684,7 +684,7 @@ static struct platform_driver cpwd_driver = {
.of_match_table = cpwd_match,
},
.probe = cpwd_probe,
- .remove = __devexit_p(cpwd_remove),
+ .remove = cpwd_remove,
};
module_platform_driver(cpwd_driver);
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
index f7abbaeebcaf..8be70d8f2680 100644
--- a/drivers/watchdog/da9052_wdt.c
+++ b/drivers/watchdog/da9052_wdt.c
@@ -179,7 +179,7 @@ static const struct watchdog_ops da9052_wdt_ops = {
};
-static int __devinit da9052_wdt_probe(struct platform_device *pdev)
+static int da9052_wdt_probe(struct platform_device *pdev)
{
struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
struct da9052_wdt_data *driver_data;
@@ -224,7 +224,7 @@ err:
return ret;
}
-static int __devexit da9052_wdt_remove(struct platform_device *pdev)
+static int da9052_wdt_remove(struct platform_device *pdev)
{
struct da9052_wdt_data *driver_data = dev_get_drvdata(&pdev->dev);
@@ -236,7 +236,7 @@ static int __devexit da9052_wdt_remove(struct platform_device *pdev)
static struct platform_driver da9052_wdt_driver = {
.probe = da9052_wdt_probe,
- .remove = __devexit_p(da9052_wdt_remove),
+ .remove = da9052_wdt_remove,
.driver = {
.name = "da9052-watchdog",
},
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index c8c5c8032bcb..8791879e5181 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -199,7 +199,7 @@ static struct miscdevice davinci_wdt_miscdev = {
.fops = &davinci_wdt_fops,
};
-static int __devinit davinci_wdt_probe(struct platform_device *pdev)
+static int davinci_wdt_probe(struct platform_device *pdev)
{
int ret = 0, size;
struct device *dev = &pdev->dev;
@@ -248,7 +248,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit davinci_wdt_remove(struct platform_device *pdev)
+static int davinci_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&davinci_wdt_miscdev);
if (wdt_mem) {
@@ -268,7 +268,7 @@ static struct platform_driver platform_wdt_driver = {
.owner = THIS_MODULE,
},
.probe = davinci_wdt_probe,
- .remove = __devexit_p(davinci_wdt_remove),
+ .remove = davinci_wdt_remove,
};
module_platform_driver(platform_wdt_driver);
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 06de1211a444..a0eba3c40e25 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -293,7 +293,7 @@ static struct miscdevice dw_wdt_miscdev = {
.minor = WATCHDOG_MINOR,
};
-static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+static int dw_wdt_drv_probe(struct platform_device *pdev)
{
int ret;
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -333,7 +333,7 @@ out_put_clk:
return ret;
}
-static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+static int dw_wdt_drv_remove(struct platform_device *pdev)
{
misc_deregister(&dw_wdt_miscdev);
@@ -345,7 +345,7 @@ static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
static struct platform_driver dw_wdt_driver = {
.probe = dw_wdt_drv_probe,
- .remove = __devexit_p(dw_wdt_drv_remove),
+ .remove = dw_wdt_drv_remove,
.driver = {
.name = "dw_wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index 77050037597a..e0574844c313 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -112,7 +112,7 @@ static struct watchdog_device ep93xx_wdt_wdd = {
.ops = &ep93xx_wdt_ops,
};
-static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
+static int ep93xx_wdt_probe(struct platform_device *pdev)
{
struct resource *res;
unsigned long val;
@@ -156,7 +156,7 @@ static int __devinit ep93xx_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ep93xx_wdt_remove(struct platform_device *pdev)
+static int ep93xx_wdt_remove(struct platform_device *pdev)
{
watchdog_unregister_device(&ep93xx_wdt_wdd);
return 0;
@@ -168,7 +168,7 @@ static struct platform_driver ep93xx_wdt_driver = {
.name = "ep93xx-wdt",
},
.probe = ep93xx_wdt_probe,
- .remove = __devexit_p(ep93xx_wdt_remove),
+ .remove = ep93xx_wdt_remove,
};
module_platform_driver(ep93xx_wdt_driver);
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 17f4cae770c6..b9c5b58e59d3 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -262,7 +262,7 @@ static struct miscdevice gef_wdt_miscdev = {
};
-static int __devinit gef_wdt_probe(struct platform_device *dev)
+static int gef_wdt_probe(struct platform_device *dev)
{
int timeout = 10;
u32 freq;
@@ -285,7 +285,7 @@ static int __devinit gef_wdt_probe(struct platform_device *dev)
return misc_register(&gef_wdt_miscdev);
}
-static int __devexit gef_wdt_remove(struct platform_device *dev)
+static int gef_wdt_remove(struct platform_device *dev)
{
misc_deregister(&gef_wdt_miscdev);
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index dc563b680abd..fcd599d4e225 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -215,7 +215,7 @@ static struct miscdevice geodewdt_miscdev = {
.fops = &geodewdt_fops,
};
-static int __devinit geodewdt_probe(struct platform_device *dev)
+static int geodewdt_probe(struct platform_device *dev)
{
int ret;
@@ -243,7 +243,7 @@ static int __devinit geodewdt_probe(struct platform_device *dev)
return ret;
}
-static int __devexit geodewdt_remove(struct platform_device *dev)
+static int geodewdt_remove(struct platform_device *dev)
{
misc_deregister(&geodewdt_miscdev);
return 0;
@@ -256,7 +256,7 @@ static void geodewdt_shutdown(struct platform_device *dev)
static struct platform_driver geodewdt_driver = {
.probe = geodewdt_probe,
- .remove = __devexit_p(geodewdt_remove),
+ .remove = geodewdt_remove,
.shutdown = geodewdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index ae60406ea8a1..8717255ec7be 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -212,7 +212,7 @@ asm(".text \n\t"
* 0 : SUCCESS
* <0 : FAILURE
*/
-static int __devinit cru_detect(unsigned long map_entry,
+static int cru_detect(unsigned long map_entry,
unsigned long map_offset)
{
void *bios32_map;
@@ -268,7 +268,7 @@ static int __devinit cru_detect(unsigned long map_entry,
/*
* bios_checksum
*/
-static int __devinit bios_checksum(const char __iomem *ptr, int len)
+static int bios_checksum(const char __iomem *ptr, int len)
{
char sum = 0;
int i;
@@ -293,7 +293,7 @@ static int __devinit bios_checksum(const char __iomem *ptr, int len)
* 0 : SUCCESS
* <0 : FAILURE
*/
-static int __devinit bios32_present(const char __iomem *p)
+static int bios32_present(const char __iomem *p)
{
struct bios32_service_dir *bios_32_ptr;
int length;
@@ -323,7 +323,7 @@ static int __devinit bios32_present(const char __iomem *p)
return -ENODEV;
}
-static int __devinit detect_cru_service(void)
+static int detect_cru_service(void)
{
char __iomem *p, *q;
int rc = -1;
@@ -395,7 +395,7 @@ asm(".text \n\t"
* This function checks whether or not a SMBIOS/DMI record is
* the 64bit CRU info or not
*/
-static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
+static void dmi_find_cru(const struct dmi_header *dm, void *dummy)
{
struct smbios_cru64_info *smbios_cru64_ptr;
unsigned long cru_physical_address;
@@ -414,7 +414,7 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy)
}
}
-static int __devinit detect_cru_service(void)
+static int detect_cru_service(void)
{
cru_rom_addr = NULL;
@@ -647,7 +647,7 @@ static struct miscdevice hpwdt_miscdev = {
#ifdef CONFIG_HPWDT_NMI_DECODING
#ifdef CONFIG_X86_LOCAL_APIC
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
{
/*
* If nmi_watchdog is turned off then we can turn on
@@ -656,7 +656,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
hpwdt_nmi_decoding = 1;
}
#else
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
{
dev_warn(&dev->dev, "NMI decoding is disabled. "
"Your kernel does not support a NMI Watchdog.\n");
@@ -671,7 +671,7 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
* This check is independent of architecture and needs to be made for
* any ProLiant system.
*/
-static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
+static void dmi_find_icru(const struct dmi_header *dm, void *dummy)
{
struct smbios_proliant_info *smbios_proliant_ptr;
@@ -682,7 +682,7 @@ static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
}
}
-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
+static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
{
int retval;
@@ -762,11 +762,11 @@ static void hpwdt_exit_nmi_decoding(void)
iounmap(cru_rom_addr);
}
#else /* !CONFIG_HPWDT_NMI_DECODING */
-static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
+static void hpwdt_check_nmi_decoding(struct pci_dev *dev)
{
}
-static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
+static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
{
return 0;
}
@@ -776,7 +776,7 @@ static void hpwdt_exit_nmi_decoding(void)
}
#endif /* CONFIG_HPWDT_NMI_DECODING */
-static int __devinit hpwdt_init_one(struct pci_dev *dev,
+static int hpwdt_init_one(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int retval;
@@ -848,7 +848,7 @@ error_pci_iomap:
return retval;
}
-static void __devexit hpwdt_exit(struct pci_dev *dev)
+static void hpwdt_exit(struct pci_dev *dev)
{
if (!nowayout)
hpwdt_stop();
@@ -863,7 +863,7 @@ static struct pci_driver hpwdt_driver = {
.name = "hpwdt",
.id_table = hpwdt_devices,
.probe = hpwdt_init_one,
- .remove = __devexit_p(hpwdt_exit),
+ .remove = hpwdt_exit,
};
MODULE_AUTHOR("Tom Mingarelli");
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 276877d5b6a3..2b2ea13d03ea 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -344,7 +344,7 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
* Init & exit routines
*/
-static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
+static unsigned char esb_getdevice(struct pci_dev *pdev)
{
if (pci_enable_device(pdev)) {
pr_err("failed to enable device\n");
@@ -375,7 +375,7 @@ err_devput:
return 0;
}
-static void __devinit esb_initdevice(void)
+static void esb_initdevice(void)
{
u8 val1;
u16 val2;
@@ -416,7 +416,7 @@ static void __devinit esb_initdevice(void)
esb_timer_set_heartbeat(heartbeat);
}
-static int __devinit esb_probe(struct pci_dev *pdev,
+static int esb_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int ret;
@@ -465,7 +465,7 @@ err_unmap:
return ret;
}
-static void __devexit esb_remove(struct pci_dev *pdev)
+static void esb_remove(struct pci_dev *pdev)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -488,7 +488,7 @@ static struct pci_driver esb_driver = {
.name = ESB_MODULE_NAME,
.id_table = esb_pci_tbl,
.probe = esb_probe,
- .remove = __devexit_p(esb_remove),
+ .remove = esb_remove,
.shutdown = esb_shutdown,
};
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 545d387de411..6130321da387 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -364,7 +364,7 @@ static struct watchdog_device iTCO_wdt_watchdog_dev = {
* Init & exit routines
*/
-static void __devexit iTCO_wdt_cleanup(void)
+static void iTCO_wdt_cleanup(void)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -390,7 +390,7 @@ static void __devexit iTCO_wdt_cleanup(void)
iTCO_wdt_private.gcs = NULL;
}
-static int __devinit iTCO_wdt_probe(struct platform_device *dev)
+static int iTCO_wdt_probe(struct platform_device *dev)
{
int ret = -ENODEV;
unsigned long val32;
@@ -533,7 +533,7 @@ out:
return ret;
}
-static int __devexit iTCO_wdt_remove(struct platform_device *dev)
+static int iTCO_wdt_remove(struct platform_device *dev)
{
if (iTCO_wdt_private.tco_res || iTCO_wdt_private.smi_res)
iTCO_wdt_cleanup();
@@ -548,7 +548,7 @@ static void iTCO_wdt_shutdown(struct platform_device *dev)
static struct platform_driver iTCO_wdt_driver = {
.probe = iTCO_wdt_probe,
- .remove = __devexit_p(iTCO_wdt_remove),
+ .remove = iTCO_wdt_remove,
.shutdown = iTCO_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 184c0bfc87a4..eb6b5cc98ec6 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -277,7 +277,7 @@ static struct miscdevice ibwdt_miscdev = {
* Init & exit routines
*/
-static int __devinit ibwdt_probe(struct platform_device *dev)
+static int ibwdt_probe(struct platform_device *dev)
{
int res;
@@ -319,7 +319,7 @@ out_nostopreg:
return res;
}
-static int __devexit ibwdt_remove(struct platform_device *dev)
+static int ibwdt_remove(struct platform_device *dev)
{
misc_deregister(&ibwdt_miscdev);
release_region(WDT_START, 1);
@@ -337,7 +337,7 @@ static void ibwdt_shutdown(struct platform_device *dev)
static struct platform_driver ibwdt_driver = {
.probe = ibwdt_probe,
- .remove = __devexit_p(ibwdt_remove),
+ .remove = ibwdt_remove,
.shutdown = ibwdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
index 8f541b940053..e24ef6a6e064 100644
--- a/drivers/watchdog/ie6xx_wdt.c
+++ b/drivers/watchdog/ie6xx_wdt.c
@@ -225,7 +225,7 @@ static const struct file_operations ie6xx_wdt_dbg_operations = {
.release = single_release,
};
-static void __devinit ie6xx_wdt_debugfs_init(void)
+static void ie6xx_wdt_debugfs_init(void)
{
/* /sys/kernel/debug/ie6xx_wdt */
ie6xx_wdt_data.debugfs = debugfs_create_file("ie6xx_wdt",
@@ -238,7 +238,7 @@ static void ie6xx_wdt_debugfs_exit(void)
}
#else
-static void __devinit ie6xx_wdt_debugfs_init(void)
+static void ie6xx_wdt_debugfs_init(void)
{
}
@@ -247,7 +247,7 @@ static void ie6xx_wdt_debugfs_exit(void)
}
#endif
-static int __devinit ie6xx_wdt_probe(struct platform_device *pdev)
+static int ie6xx_wdt_probe(struct platform_device *pdev)
{
struct resource *res;
u8 wdtlr;
@@ -295,7 +295,7 @@ misc_register_error:
return ret;
}
-static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
+static int ie6xx_wdt_remove(struct platform_device *pdev)
{
struct resource *res;
@@ -311,7 +311,7 @@ static int __devexit ie6xx_wdt_remove(struct platform_device *pdev)
static struct platform_driver ie6xx_wdt_driver = {
.probe = ie6xx_wdt_probe,
- .remove = __devexit_p(ie6xx_wdt_remove),
+ .remove = ie6xx_wdt_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index 978615ef899d..a61408fa0c94 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -144,7 +144,7 @@ static const struct watchdog_ops jz4740_wdt_ops = {
.set_timeout = jz4740_wdt_set_timeout,
};
-static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
+static int jz4740_wdt_probe(struct platform_device *pdev)
{
struct jz4740_wdt_drvdata *drvdata;
struct watchdog_device *jz4740_wdt;
@@ -197,7 +197,7 @@ err_out:
return ret;
}
-static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
+static int jz4740_wdt_remove(struct platform_device *pdev)
{
struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
@@ -210,7 +210,7 @@ static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
static struct platform_driver jz4740_wdt_driver = {
.probe = jz4740_wdt_probe,
- .remove = __devexit_p(jz4740_wdt_remove),
+ .remove = jz4740_wdt_remove,
.driver = {
.name = "jz4740-wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index c1a4d3bf581d..dce9ecffd44a 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -235,7 +235,7 @@ static struct miscdevice ks8695wdt_miscdev = {
.fops = &ks8695wdt_fops,
};
-static int __devinit ks8695wdt_probe(struct platform_device *pdev)
+static int ks8695wdt_probe(struct platform_device *pdev)
{
int res;
@@ -252,7 +252,7 @@ static int __devinit ks8695wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit ks8695wdt_remove(struct platform_device *pdev)
+static int ks8695wdt_remove(struct platform_device *pdev)
{
int res;
@@ -290,7 +290,7 @@ static int ks8695wdt_resume(struct platform_device *pdev)
static struct platform_driver ks8695wdt_driver = {
.probe = ks8695wdt_probe,
- .remove = __devexit_p(ks8695wdt_remove),
+ .remove = ks8695wdt_remove,
.shutdown = ks8695wdt_shutdown,
.suspend = ks8695wdt_suspend,
.resume = ks8695wdt_resume,
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index 2e74c3a8ee58..79fe01b42339 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -186,7 +186,7 @@ static struct miscdevice ltq_wdt_miscdev = {
.fops = &ltq_wdt_fops,
};
-static int __devinit
+static int
ltq_wdt_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -220,7 +220,7 @@ ltq_wdt_probe(struct platform_device *pdev)
return misc_register(&ltq_wdt_miscdev);
}
-static int __devexit
+static int
ltq_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&ltq_wdt_miscdev);
@@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, ltq_wdt_match);
static struct platform_driver ltq_wdt_driver = {
.probe = ltq_wdt_probe,
- .remove = __devexit_p(ltq_wdt_remove),
+ .remove = ltq_wdt_remove,
.driver = {
.name = "wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 8f4a74e91619..773c661723ca 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -174,7 +174,7 @@ static struct watchdog_device max63xx_wdt_dev = {
.ops = &max63xx_wdt_ops,
};
-static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
+static int max63xx_wdt_probe(struct platform_device *pdev)
{
struct resource *wdt_mem;
struct max63xx_timeout *table;
@@ -209,7 +209,7 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
return watchdog_register_device(&max63xx_wdt_dev);
}
-static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
+static int max63xx_wdt_remove(struct platform_device *pdev)
{
watchdog_unregister_device(&max63xx_wdt_dev);
return 0;
@@ -228,7 +228,7 @@ MODULE_DEVICE_TABLE(platform, max63xx_id_table);
static struct platform_driver max63xx_wdt_driver = {
.probe = max63xx_wdt_probe,
- .remove = __devexit_p(max63xx_wdt_remove),
+ .remove = max63xx_wdt_remove,
.id_table = max63xx_id_table,
.driver = {
.name = "max63xx_wdt",
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 37e4b52dbce9..97d62ee50341 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -73,7 +73,7 @@
static struct {
int ioport;
int id;
-} mixcomwd_io_info[] __devinitdata = {
+} mixcomwd_io_info[] = {
/* The Mixcom cards */
{0x0d90, MIXCOM_ID},
{0x0e90, MIXCOM_ID},
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index e6a038ae8dc2..da2752063bb7 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -188,7 +188,7 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
};
static const struct of_device_id mpc8xxx_wdt_match[];
-static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
+static int mpc8xxx_wdt_probe(struct platform_device *ofdev)
{
int ret;
const struct of_device_id *match;
@@ -245,7 +245,7 @@ err_unmap:
return ret;
}
-static int __devexit mpc8xxx_wdt_remove(struct platform_device *ofdev)
+static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
{
mpc8xxx_wdt_pr_warn("watchdog removed");
del_timer_sync(&wdt_timer);
@@ -281,7 +281,7 @@ MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
static struct platform_driver mpc8xxx_wdt_driver = {
.probe = mpc8xxx_wdt_probe,
- .remove = __devexit_p(mpc8xxx_wdt_remove),
+ .remove = mpc8xxx_wdt_remove,
.driver = {
.name = "mpc8xxx_wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 7c741dc987bd..a84eb551ea27 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -327,7 +327,7 @@ static struct miscdevice mpcore_wdt_miscdev = {
.fops = &mpcore_wdt_fops,
};
-static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
+static int mpcore_wdt_probe(struct platform_device *pdev)
{
struct mpcore_wdt *wdt;
struct resource *res;
@@ -378,7 +378,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mpcore_wdt_remove(struct platform_device *pdev)
+static int mpcore_wdt_remove(struct platform_device *pdev)
{
platform_set_drvdata(pdev, NULL);
@@ -415,7 +415,7 @@ MODULE_ALIAS("platform:mpcore_wdt");
static struct platform_driver mpcore_wdt_driver = {
.probe = mpcore_wdt_probe,
- .remove = __devexit_p(mpcore_wdt_remove),
+ .remove = mpcore_wdt_remove,
.suspend = mpcore_wdt_suspend,
.resume = mpcore_wdt_resume,
.shutdown = mpcore_wdt_shutdown,
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index c29e31d99fe8..14dab6ff87aa 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -204,7 +204,7 @@ static struct miscdevice mtx1_wdt_misc = {
};
-static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
+static int mtx1_wdt_probe(struct platform_device *pdev)
{
int ret;
@@ -233,7 +233,7 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
+static int mtx1_wdt_remove(struct platform_device *pdev)
{
/* FIXME: do we need to lock this test ? */
if (mtx1_wdt_device.queue) {
@@ -248,7 +248,7 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
static struct platform_driver mtx1_wdt_driver = {
.probe = mtx1_wdt_probe,
- .remove = __devexit_p(mtx1_wdt_remove),
+ .remove = mtx1_wdt_remove,
.driver.name = "mtx1-wdt",
.driver.owner = THIS_MODULE,
};
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index c53d025e70df..c7fb878ca493 100644
--- a/drivers/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
@@ -253,7 +253,7 @@ static struct miscdevice mv64x60_wdt_miscdev = {
.fops = &mv64x60_wdt_fops,
};
-static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
+static int mv64x60_wdt_probe(struct platform_device *dev)
{
struct mv64x60_wdt_pdata *pdata = dev->dev.platform_data;
struct resource *r;
@@ -287,7 +287,7 @@ static int __devinit mv64x60_wdt_probe(struct platform_device *dev)
return misc_register(&mv64x60_wdt_miscdev);
}
-static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
+static int mv64x60_wdt_remove(struct platform_device *dev)
{
misc_deregister(&mv64x60_wdt_miscdev);
@@ -300,7 +300,7 @@ static int __devexit mv64x60_wdt_remove(struct platform_device *dev)
static struct platform_driver mv64x60_wdt_driver = {
.probe = mv64x60_wdt_probe,
- .remove = __devexit_p(mv64x60_wdt_remove),
+ .remove = mv64x60_wdt_remove,
.driver = {
.owner = THIS_MODULE,
.name = MV64x60_WDT_NAME,
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
index ea4c7448b754..04c45a102992 100644
--- a/drivers/watchdog/nuc900_wdt.c
+++ b/drivers/watchdog/nuc900_wdt.c
@@ -242,7 +242,7 @@ static struct miscdevice nuc900wdt_miscdev = {
.fops = &nuc900wdt_fops,
};
-static int __devinit nuc900wdt_probe(struct platform_device *pdev)
+static int nuc900wdt_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -309,7 +309,7 @@ err_get:
return ret;
}
-static int __devexit nuc900wdt_remove(struct platform_device *pdev)
+static int nuc900wdt_remove(struct platform_device *pdev)
{
misc_deregister(&nuc900wdt_miscdev);
@@ -328,7 +328,7 @@ static int __devexit nuc900wdt_remove(struct platform_device *pdev)
static struct platform_driver nuc900wdt_driver = {
.probe = nuc900wdt_probe,
- .remove = __devexit_p(nuc900wdt_remove),
+ .remove = nuc900wdt_remove,
.driver = {
.name = "nuc900-wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
index 6bbb9efc6125..59cf19eeea07 100644
--- a/drivers/watchdog/nv_tco.c
+++ b/drivers/watchdog/nv_tco.c
@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(pci, tco_pci_tbl);
* Init & exit routines
*/
-static unsigned char __devinit nv_tco_getdevice(void)
+static unsigned char nv_tco_getdevice(void)
{
struct pci_dev *dev = NULL;
u32 val;
@@ -376,7 +376,7 @@ out:
return 0;
}
-static int __devinit nv_tco_init(struct platform_device *dev)
+static int nv_tco_init(struct platform_device *dev)
{
int ret;
@@ -423,7 +423,7 @@ unreg_region:
return ret;
}
-static void __devexit nv_tco_cleanup(void)
+static void nv_tco_cleanup(void)
{
u32 val;
@@ -445,7 +445,7 @@ static void __devexit nv_tco_cleanup(void)
release_region(tcobase, 0x10);
}
-static int __devexit nv_tco_remove(struct platform_device *dev)
+static int nv_tco_remove(struct platform_device *dev)
{
if (tcobase)
nv_tco_cleanup();
@@ -468,7 +468,7 @@ static void nv_tco_shutdown(struct platform_device *dev)
static struct platform_driver nv_tco_driver = {
.probe = nv_tco_init,
- .remove = __devexit_p(nv_tco_remove),
+ .remove = nv_tco_remove,
.shutdown = nv_tco_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 294fb4e00521..2761ddb08501 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -289,7 +289,7 @@ static struct miscdevice xwdt_miscdev = {
.fops = &xwdt_fops,
};
-static int __devinit xwdt_probe(struct platform_device *pdev)
+static int xwdt_probe(struct platform_device *pdev)
{
int rc;
u32 *tmptr;
@@ -383,7 +383,7 @@ err_out:
return rc;
}
-static int __devexit xwdt_remove(struct platform_device *dev)
+static int xwdt_remove(struct platform_device *dev)
{
misc_deregister(&xwdt_miscdev);
iounmap(xdev.base);
@@ -393,7 +393,7 @@ static int __devexit xwdt_remove(struct platform_device *dev)
}
/* Match table for of_platform binding */
-static struct of_device_id __devinitdata xwdt_of_match[] = {
+static struct of_device_id xwdt_of_match[] = {
{ .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
{},
};
@@ -401,7 +401,7 @@ MODULE_DEVICE_TABLE(of, xwdt_of_match);
static struct platform_driver xwdt_driver = {
.probe = xwdt_probe,
- .remove = __devexit_p(xwdt_remove),
+ .remove = xwdt_remove,
.driver = {
.owner = THIS_MODULE,
.name = WATCHDOG_NAME,
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index f5db18dbc0f9..d8da5162f0dd 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -264,7 +264,7 @@ static const struct file_operations omap_wdt_fops = {
.llseek = no_llseek,
};
-static int __devinit omap_wdt_probe(struct platform_device *pdev)
+static int omap_wdt_probe(struct platform_device *pdev)
{
struct resource *res, *mem;
struct omap_wdt_dev *wdev;
@@ -359,7 +359,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
}
}
-static int __devexit omap_wdt_remove(struct platform_device *pdev)
+static int omap_wdt_remove(struct platform_device *pdev)
{
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -426,7 +426,7 @@ MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
static struct platform_driver omap_wdt_driver = {
.probe = omap_wdt_probe,
- .remove = __devexit_p(omap_wdt_remove),
+ .remove = omap_wdt_remove,
.shutdown = omap_wdt_shutdown,
.suspend = omap_wdt_suspend,
.resume = omap_wdt_resume,
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index c20f96b579d9..0478b001b1ef 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -142,7 +142,7 @@ static struct watchdog_device orion_wdt = {
.ops = &orion_wdt_ops,
};
-static int __devinit orion_wdt_probe(struct platform_device *pdev)
+static int orion_wdt_probe(struct platform_device *pdev)
{
struct resource *res;
int ret;
@@ -181,7 +181,7 @@ static int __devinit orion_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit orion_wdt_remove(struct platform_device *pdev)
+static int orion_wdt_remove(struct platform_device *pdev)
{
watchdog_unregister_device(&orion_wdt);
clk_disable_unprepare(clk);
@@ -193,7 +193,7 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
orion_wdt_stop(&orion_wdt);
}
-static const struct of_device_id orion_wdt_of_match_table[] __devinitdata = {
+static const struct of_device_id orion_wdt_of_match_table[] = {
{ .compatible = "marvell,orion-wdt", },
{},
};
@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, orion_wdt_of_match_table);
static struct platform_driver orion_wdt_driver = {
.probe = orion_wdt_probe,
- .remove = __devexit_p(orion_wdt_remove),
+ .remove = orion_wdt_remove,
.shutdown = orion_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 75694cf24f86..33e49a7f889f 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -801,7 +801,7 @@ static inline int get_revision(void)
* The initial rate is once per second at board start up, then twice
* per second for normal operation.
*/
-static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
+static int pcwd_isa_match(struct device *dev, unsigned int id)
{
int base_addr = pcwd_ioports[id];
int port0, last_port0; /* Reg 0, in case it's REV A */
@@ -846,7 +846,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
return retval;
}
-static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
+static int pcwd_isa_probe(struct device *dev, unsigned int id)
{
int ret;
@@ -949,7 +949,7 @@ error_request_region:
return ret;
}
-static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
+static int pcwd_isa_remove(struct device *dev, unsigned int id)
{
if (debug >= DEBUG)
pr_debug("pcwd_isa_remove id=%d\n", id);
@@ -984,7 +984,7 @@ static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
static struct isa_driver pcwd_isa_driver = {
.match = pcwd_isa_match,
.probe = pcwd_isa_probe,
- .remove = __devexit_p(pcwd_isa_remove),
+ .remove = pcwd_isa_remove,
.shutdown = pcwd_isa_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index ee6900da8678..7890f84edf76 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -682,7 +682,7 @@ static struct notifier_block pcipcwd_notifier = {
* Init & exit routines
*/
-static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
+static int pcipcwd_card_init(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int ret = -EIO;
@@ -785,7 +785,7 @@ err_out_disable_device:
return ret;
}
-static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
+static void pcipcwd_card_exit(struct pci_dev *pdev)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -812,7 +812,7 @@ static struct pci_driver pcipcwd_driver = {
.name = WATCHDOG_NAME,
.id_table = pcipcwd_pci_tbl,
.probe = pcipcwd_card_init,
- .remove = __devexit_p(pcipcwd_card_exit),
+ .remove = pcipcwd_card_exit,
};
module_pci_driver(pcipcwd_driver);
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index 87722e126058..dcba5dab6c29 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -146,7 +146,7 @@ static struct watchdog_device pnx4008_wdd = {
.max_timeout = MAX_HEARTBEAT,
};
-static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
+static int pnx4008_wdt_probe(struct platform_device *pdev)
{
struct resource *r;
int ret = 0;
@@ -192,7 +192,7 @@ out:
return ret;
}
-static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
+static int pnx4008_wdt_remove(struct platform_device *pdev)
{
watchdog_unregister_device(&pnx4008_wdd);
@@ -217,7 +217,7 @@ static struct platform_driver platform_wdt_driver = {
.of_match_table = of_match_ptr(pnx4008_wdt_match),
},
.probe = pnx4008_wdt_probe,
- .remove = __devexit_p(pnx4008_wdt_remove),
+ .remove = pnx4008_wdt_remove,
};
module_platform_driver(platform_wdt_driver);
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index 547353a50ebb..f78bc008cbb7 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -260,7 +260,7 @@ static struct miscdevice rc32434_wdt_miscdev = {
.fops = &rc32434_wdt_fops,
};
-static int __devinit rc32434_wdt_probe(struct platform_device *pdev)
+static int rc32434_wdt_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
@@ -306,7 +306,7 @@ unmap:
return ret;
}
-static int __devexit rc32434_wdt_remove(struct platform_device *pdev)
+static int rc32434_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&rc32434_wdt_miscdev);
iounmap(wdt_reg);
@@ -320,7 +320,7 @@ static void rc32434_wdt_shutdown(struct platform_device *pdev)
static struct platform_driver rc32434_wdt_driver = {
.probe = rc32434_wdt_probe,
- .remove = __devexit_p(rc32434_wdt_remove),
+ .remove = rc32434_wdt_remove,
.shutdown = rc32434_wdt_shutdown,
.driver = {
.name = "rc32434_wdt",
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 042ccc56ae26..b0f116c2fd53 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -225,7 +225,7 @@ static struct miscdevice rdc321x_wdt_misc = {
.fops = &rdc321x_wdt_fops,
};
-static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
+static int rdc321x_wdt_probe(struct platform_device *pdev)
{
int err;
struct resource *r;
@@ -272,7 +272,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
+static int rdc321x_wdt_remove(struct platform_device *pdev)
{
if (rdc321x_wdt_device.queue) {
rdc321x_wdt_device.queue = 0;
@@ -286,7 +286,7 @@ static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
static struct platform_driver rdc321x_wdt_driver = {
.probe = rdc321x_wdt_probe,
- .remove = __devexit_p(rdc321x_wdt_remove),
+ .remove = rdc321x_wdt_remove,
.driver = {
.owner = THIS_MODULE,
.name = "rdc321x-wdt",
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 49e1b1c2135c..0040451aec1d 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -174,7 +174,7 @@ static struct miscdevice riowd_miscdev = {
.fops = &riowd_fops
};
-static int __devinit riowd_probe(struct platform_device *op)
+static int riowd_probe(struct platform_device *op)
{
struct riowd *p;
int err = -EINVAL;
@@ -220,7 +220,7 @@ out:
return err;
}
-static int __devexit riowd_remove(struct platform_device *op)
+static int riowd_remove(struct platform_device *op)
{
struct riowd *p = dev_get_drvdata(&op->dev);
@@ -246,7 +246,7 @@ static struct platform_driver riowd_driver = {
.of_match_table = riowd_match,
},
.probe = riowd_probe,
- .remove = __devexit_p(riowd_remove),
+ .remove = riowd_remove,
};
module_platform_driver(riowd_driver);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 9245b4d23bfe..b0dab10fc6a5 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -303,7 +303,7 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
}
#endif
-static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
+static int s3c2410wdt_probe(struct platform_device *pdev)
{
struct device *dev;
unsigned int wtcon;
@@ -437,7 +437,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit s3c2410wdt_remove(struct platform_device *dev)
+static int s3c2410wdt_remove(struct platform_device *dev)
{
watchdog_unregister_device(&s3c2410_wdd);
@@ -508,7 +508,7 @@ MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
static struct platform_driver s3c2410wdt_driver = {
.probe = s3c2410wdt_probe,
- .remove = __devexit_p(s3c2410wdt_remove),
+ .remove = s3c2410wdt_remove,
.shutdown = s3c2410wdt_shutdown,
.suspend = s3c2410wdt_suspend,
.resume = s3c2410wdt_resume,
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 9681ada0f252..af7b136b1874 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -356,7 +356,7 @@ static struct miscdevice sch311x_wdt_miscdev = {
* Init & exit routines
*/
-static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
+static int sch311x_wdt_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int err;
@@ -429,7 +429,7 @@ exit:
return err;
}
-static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
+static int sch311x_wdt_remove(struct platform_device *pdev)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -451,7 +451,7 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
static struct platform_driver sch311x_wdt_driver = {
.probe = sch311x_wdt_probe,
- .remove = __devexit_p(sch311x_wdt_remove),
+ .remove = sch311x_wdt_remove,
.shutdown = sch311x_wdt_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index e5b59bebcdb1..6a89e4045fbd 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -217,7 +217,7 @@ static struct watchdog_device sh_wdt_dev = {
.ops = &sh_wdt_ops,
};
-static int __devinit sh_wdt_probe(struct platform_device *pdev)
+static int sh_wdt_probe(struct platform_device *pdev)
{
struct sh_wdt *wdt;
struct resource *res;
@@ -298,7 +298,7 @@ err:
return rc;
}
-static int __devexit sh_wdt_remove(struct platform_device *pdev)
+static int sh_wdt_remove(struct platform_device *pdev)
{
struct sh_wdt *wdt = platform_get_drvdata(pdev);
@@ -324,7 +324,7 @@ static struct platform_driver sh_wdt_driver = {
},
.probe = sh_wdt_probe,
- .remove = __devexit_p(sh_wdt_remove),
+ .remove = sh_wdt_remove,
.shutdown = sh_wdt_shutdown,
};
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index ae5e82cb83fa..b3876812ff07 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -271,7 +271,7 @@ MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl);
* Init & exit routines
*/
-static unsigned char __devinit sp5100_tco_setupdevice(void)
+static unsigned char sp5100_tco_setupdevice(void)
{
struct pci_dev *dev = NULL;
u32 val;
@@ -361,7 +361,7 @@ exit:
return 0;
}
-static int __devinit sp5100_tco_init(struct platform_device *dev)
+static int sp5100_tco_init(struct platform_device *dev)
{
int ret;
u32 val;
@@ -412,7 +412,7 @@ exit:
return ret;
}
-static void __devexit sp5100_tco_cleanup(void)
+static void sp5100_tco_cleanup(void)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -425,7 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
}
-static int __devexit sp5100_tco_remove(struct platform_device *dev)
+static int sp5100_tco_remove(struct platform_device *dev)
{
if (tcobase)
sp5100_tco_cleanup();
@@ -439,7 +439,7 @@ static void sp5100_tco_shutdown(struct platform_device *dev)
static struct platform_driver sp5100_tco_driver = {
.probe = sp5100_tco_init,
- .remove = __devexit_p(sp5100_tco_remove),
+ .remove = sp5100_tco_remove,
.shutdown = sp5100_tco_shutdown,
.driver = {
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index e4841c36798b..4552847fc7fe 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -210,7 +210,7 @@ static const struct watchdog_ops wdt_ops = {
.get_timeleft = wdt_timeleft,
};
-static int __devinit
+static int
sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
{
struct sp805_wdt *wdt;
@@ -272,7 +272,7 @@ err:
return ret;
}
-static int __devexit sp805_wdt_remove(struct amba_device *adev)
+static int sp805_wdt_remove(struct amba_device *adev)
{
struct sp805_wdt *wdt = amba_get_drvdata(adev);
@@ -326,7 +326,7 @@ static struct amba_driver sp805_wdt_driver = {
},
.id_table = sp805_wdt_ids,
.probe = sp805_wdt_probe,
- .remove = __devexit_p(sp805_wdt_remove),
+ .remove = sp805_wdt_remove,
};
module_amba_driver(sp805_wdt_driver);
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
index 21d96b92bfd7..1f4f69728fee 100644
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ b/drivers/watchdog/stmp3xxx_wdt.c
@@ -204,7 +204,7 @@ static struct miscdevice stmp3xxx_wdt_miscdev = {
.fops = &stmp3xxx_wdt_fops,
};
-static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
+static int stmp3xxx_wdt_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -229,7 +229,7 @@ static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev)
return ret;
}
-static int __devexit stmp3xxx_wdt_remove(struct platform_device *pdev)
+static int stmp3xxx_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&stmp3xxx_wdt_miscdev);
return 0;
@@ -269,7 +269,7 @@ static struct platform_driver platform_wdt_driver = {
.name = "stmp3xxx_wdt",
},
.probe = stmp3xxx_wdt_probe,
- .remove = __devexit_p(stmp3xxx_wdt_remove),
+ .remove = stmp3xxx_wdt_remove,
.suspend = stmp3xxx_wdt_suspend,
.resume = stmp3xxx_wdt_resume,
};
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 8df050d800e6..b8a92459f10f 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -390,7 +390,7 @@ static struct miscdevice ts72xx_wdt_miscdev = {
.fops = &ts72xx_wdt_fops,
};
-static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
+static int ts72xx_wdt_probe(struct platform_device *pdev)
{
struct ts72xx_wdt *wdt;
struct resource *r1, *r2;
@@ -476,7 +476,7 @@ fail:
return error;
}
-static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
+static int ts72xx_wdt_remove(struct platform_device *pdev)
{
struct ts72xx_wdt *wdt = platform_get_drvdata(pdev);
struct resource *res;
@@ -499,7 +499,7 @@ static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
static struct platform_driver ts72xx_wdt_driver = {
.probe = ts72xx_wdt_probe,
- .remove = __devexit_p(ts72xx_wdt_remove),
+ .remove = ts72xx_wdt_remove,
.driver = {
.name = "ts72xx-wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index 249f11305d26..9f54b1da7185 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -170,7 +170,7 @@ static const struct file_operations twl4030_wdt_fops = {
.write = twl4030_wdt_write_fop,
};
-static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
+static int twl4030_wdt_probe(struct platform_device *pdev)
{
int ret = 0;
struct twl4030_wdt *wdt;
@@ -204,7 +204,7 @@ static int __devinit twl4030_wdt_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit twl4030_wdt_remove(struct platform_device *pdev)
+static int twl4030_wdt_remove(struct platform_device *pdev)
{
struct twl4030_wdt *wdt = platform_get_drvdata(pdev);
@@ -247,7 +247,7 @@ static int twl4030_wdt_resume(struct platform_device *pdev)
static struct platform_driver twl4030_wdt_driver = {
.probe = twl4030_wdt_probe,
- .remove = __devexit_p(twl4030_wdt_remove),
+ .remove = twl4030_wdt_remove,
.suspend = twl4030_wdt_suspend,
.resume = twl4030_wdt_resume,
.driver = {
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index aa50da3ccfe3..1a68f760cf86 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -155,7 +155,7 @@ static struct watchdog_device wdt_dev = {
.max_timeout = WDT_TIMEOUT_MAX,
};
-static int __devinit wdt_probe(struct pci_dev *pdev,
+static int wdt_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
unsigned char conf;
@@ -229,7 +229,7 @@ err_out_disable_device:
return ret;
}
-static void __devexit wdt_remove(struct pci_dev *pdev)
+static void wdt_remove(struct pci_dev *pdev)
{
watchdog_unregister_device(&wdt_dev);
del_timer(&timer);
@@ -250,7 +250,7 @@ static struct pci_driver wdt_driver = {
.name = "via_wdt",
.id_table = wdt_pci_table,
.probe = wdt_probe,
- .remove = __devexit_p(wdt_remove),
+ .remove = wdt_remove,
};
module_pci_driver(wdt_driver);
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index e32654efdbb6..36a54c0e32dd 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -605,7 +605,7 @@ static struct notifier_block wdtpci_notifier = {
};
-static int __devinit wdtpci_init_one(struct pci_dev *dev,
+static int wdtpci_init_one(struct pci_dev *dev,
const struct pci_device_id *ent)
{
int ret = -EIO;
@@ -705,7 +705,7 @@ out_pci:
}
-static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
+static void wdtpci_remove_one(struct pci_dev *pdev)
{
/* here we assume only one device will ever have
* been picked up and registered by probe function */
@@ -736,7 +736,7 @@ static struct pci_driver wdtpci_driver = {
.name = "wdt_pci",
.id_table = wdtpci_pci_tbl,
.probe = wdtpci_init_one,
- .remove = __devexit_p(wdtpci_remove_one),
+ .remove = wdtpci_remove_one,
};
module_pci_driver(wdtpci_driver);
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index 87d66d236c3e..9dcb6d082277 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -181,7 +181,7 @@ static const struct watchdog_ops wm831x_wdt_ops = {
.set_timeout = wm831x_wdt_set_timeout,
};
-static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
+static int wm831x_wdt_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_pdata *chip_pdata;
@@ -292,7 +292,7 @@ err:
return ret;
}
-static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
+static int wm831x_wdt_remove(struct platform_device *pdev)
{
struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev);
@@ -306,7 +306,7 @@ static int __devexit wm831x_wdt_remove(struct platform_device *pdev)
static struct platform_driver wm831x_wdt_driver = {
.probe = wm831x_wdt_probe,
- .remove = __devexit_p(wm831x_wdt_remove),
+ .remove = wm831x_wdt_remove,
.driver = {
.name = "wm831x-watchdog",
},
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 3c76693447fd..34d272ada23d 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -140,7 +140,7 @@ static struct watchdog_device wm8350_wdt = {
.max_timeout = 4,
};
-static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
+static int wm8350_wdt_probe(struct platform_device *pdev)
{
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
@@ -158,7 +158,7 @@ static int __devinit wm8350_wdt_probe(struct platform_device *pdev)
return watchdog_register_device(&wm8350_wdt);
}
-static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
+static int wm8350_wdt_remove(struct platform_device *pdev)
{
watchdog_unregister_device(&wm8350_wdt);
return 0;
@@ -166,7 +166,7 @@ static int __devexit wm8350_wdt_remove(struct platform_device *pdev)
static struct platform_driver wm8350_wdt_driver = {
.probe = wm8350_wdt_probe,
- .remove = __devexit_p(wm8350_wdt_remove),
+ .remove = wm8350_wdt_remove,
.driver = {
.name = "wm8350-wdt",
},
diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
index e4a25b51165c..92ad33d0cb71 100644
--- a/drivers/watchdog/xen_wdt.c
+++ b/drivers/watchdog/xen_wdt.c
@@ -244,7 +244,7 @@ static struct miscdevice xen_wdt_miscdev = {
.fops = &xen_wdt_fops,
};
-static int __devinit xen_wdt_probe(struct platform_device *dev)
+static int xen_wdt_probe(struct platform_device *dev)
{
struct sched_watchdog wd = { .id = ~0 };
int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd);
@@ -280,7 +280,7 @@ static int __devinit xen_wdt_probe(struct platform_device *dev)
return ret;
}
-static int __devexit xen_wdt_remove(struct platform_device *dev)
+static int xen_wdt_remove(struct platform_device *dev)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -315,7 +315,7 @@ static int xen_wdt_resume(struct platform_device *dev)
static struct platform_driver xen_wdt_driver = {
.probe = xen_wdt_probe,
- .remove = __devexit_p(xen_wdt_remove),
+ .remove = xen_wdt_remove,
.shutdown = xen_wdt_shutdown,
.suspend = xen_wdt_suspend,
.resume = xen_wdt_resume,
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 8adb9cc267f9..71f5c459b088 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
down_write(&mm->mmap_sem);
vma = find_vma(mm, m.addr);
- ret = -EINVAL;
if (!vma ||
vma->vm_ops != &privcmd_vm_ops ||
(m.addr != vma->vm_start) ||
((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
!privcmd_enforce_singleshot_mapping(vma)) {
up_write(&mm->mmap_sem);
+ ret = -EINVAL;
goto out;
}
@@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
up_write(&mm->mmap_sem);
- if (state.global_error && (version == 1)) {
- /* Write back errors in second pass. */
- state.user_mfn = (xen_pfn_t *)m.arr;
- state.err = err_array;
- ret = traverse_pages(m.num, sizeof(xen_pfn_t),
- &pagelist, mmap_return_errors_v1, &state);
+ if (version == 1) {
+ if (state.global_error) {
+ /* Write back errors in second pass. */
+ state.user_mfn = (xen_pfn_t *)m.arr;
+ state.err = err_array;
+ ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+ &pagelist, mmap_return_errors_v1, &state);
+ } else
+ ret = 0;
+
} else if (version == 2) {
ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
if (ret)
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c
index 7d041cb6da26..2552d3e0a70f 100644
--- a/drivers/xen/xen-selfballoon.c
+++ b/drivers/xen/xen-selfballoon.c
@@ -222,7 +222,7 @@ static void selfballoon_process(struct work_struct *work)
if (xen_selfballooning_enabled) {
cur_pages = totalram_pages;
tgt_pages = cur_pages; /* default is no change */
- goal_pages = percpu_counter_read_positive(&vm_committed_as) +
+ goal_pages = vm_memory_committed() +
totalreserve_pages +
MB2PAGES(selfballoon_reserved_mb);
#ifdef CONFIG_FRONTSWAP
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1a1e5e3b1eaf..ab3a456f6650 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -70,19 +70,6 @@ static void bdev_inode_switch_bdi(struct inode *inode,
spin_unlock(&dst->wb.list_lock);
}
-sector_t blkdev_max_block(struct block_device *bdev)
-{
- sector_t retval = ~((sector_t)0);
- loff_t sz = i_size_read(bdev->bd_inode);
-
- if (sz) {
- unsigned int size = block_size(bdev);
- unsigned int sizebits = blksize_bits(size);
- retval = (sz >> sizebits);
- }
- return retval;
-}
-
/* Kill _all_ buffers and pagecache , dirty or not.. */
void kill_bdev(struct block_device *bdev)
{
@@ -116,8 +103,6 @@ EXPORT_SYMBOL(invalidate_bdev);
int set_blocksize(struct block_device *bdev, int size)
{
- struct address_space *mapping;
-
/* Size must be a power of two, and between 512 and PAGE_SIZE */
if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
return -EINVAL;
@@ -126,19 +111,6 @@ int set_blocksize(struct block_device *bdev, int size)
if (size < bdev_logical_block_size(bdev))
return -EINVAL;
- /* Prevent starting I/O or mapping the device */
- percpu_down_write(&bdev->bd_block_size_semaphore);
-
- /* Check that the block device is not memory mapped */
- mapping = bdev->bd_inode->i_mapping;
- mutex_lock(&mapping->i_mmap_mutex);
- if (mapping_mapped(mapping)) {
- mutex_unlock(&mapping->i_mmap_mutex);
- percpu_up_write(&bdev->bd_block_size_semaphore);
- return -EBUSY;
- }
- mutex_unlock(&mapping->i_mmap_mutex);
-
/* Don't change the size if it is same as current */
if (bdev->bd_block_size != size) {
sync_blockdev(bdev);
@@ -146,9 +118,6 @@ int set_blocksize(struct block_device *bdev, int size)
bdev->bd_inode->i_blkbits = blksize_bits(size);
kill_bdev(bdev);
}
-
- percpu_up_write(&bdev->bd_block_size_semaphore);
-
return 0;
}
@@ -181,52 +150,12 @@ static int
blkdev_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- if (iblock >= blkdev_max_block(I_BDEV(inode))) {
- if (create)
- return -EIO;
-
- /*
- * for reads, we're just trying to fill a partial page.
- * return a hole, they will have to call get_block again
- * before they can fill it, and they will get -EIO at that
- * time
- */
- return 0;
- }
bh->b_bdev = I_BDEV(inode);
bh->b_blocknr = iblock;
set_buffer_mapped(bh);
return 0;
}
-static int
-blkdev_get_blocks(struct inode *inode, sector_t iblock,
- struct buffer_head *bh, int create)
-{
- 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) {
- max_blocks = end_block - iblock;
- if ((long)max_blocks <= 0) {
- if (create)
- return -EIO; /* write fully beyond EOF */
- /*
- * It is a read which is fully beyond EOF. We return
- * a !buffer_mapped buffer
- */
- max_blocks = 0;
- }
- }
-
- bh->b_bdev = I_BDEV(inode);
- bh->b_blocknr = iblock;
- bh->b_size = max_blocks << inode->i_blkbits;
- if (max_blocks)
- set_buffer_mapped(bh);
- return 0;
-}
-
static ssize_t
blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
loff_t offset, unsigned long nr_segs)
@@ -235,7 +164,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
struct inode *inode = file->f_mapping->host;
return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
- nr_segs, blkdev_get_blocks, NULL, NULL, 0);
+ nr_segs, blkdev_get_block, NULL, NULL, 0);
}
int __sync_blockdev(struct block_device *bdev, int wait)
@@ -459,12 +388,6 @@ static struct inode *bdev_alloc_inode(struct super_block *sb)
struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);
if (!ei)
return NULL;
-
- if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) {
- kmem_cache_free(bdev_cachep, ei);
- return NULL;
- }
-
return &ei->vfs_inode;
}
@@ -473,8 +396,6 @@ static void bdev_i_callback(struct rcu_head *head)
struct inode *inode = container_of(head, struct inode, i_rcu);
struct bdev_inode *bdi = BDEV_I(inode);
- percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore);
-
kmem_cache_free(bdev_cachep, bdi);
}
@@ -1593,22 +1514,6 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
return blkdev_ioctl(bdev, mode, cmd, arg);
}
-ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
-{
- ssize_t ret;
- struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
-
- percpu_down_read(&bdev->bd_block_size_semaphore);
-
- ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
-
- percpu_up_read(&bdev->bd_block_size_semaphore);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(blkdev_aio_read);
-
/*
* Write data to the block device. Only intended for the block device itself
* and the raw driver which basically is a fake block device.
@@ -1620,16 +1525,12 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
struct file *file = iocb->ki_filp;
- struct block_device *bdev = I_BDEV(file->f_mapping->host);
struct blk_plug plug;
ssize_t ret;
BUG_ON(iocb->ki_pos != pos);
blk_start_plug(&plug);
-
- percpu_down_read(&bdev->bd_block_size_semaphore);
-
ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
if (ret > 0 || ret == -EIOCBQUEUED) {
ssize_t err;
@@ -1638,62 +1539,27 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (err < 0 && ret > 0)
ret = err;
}
-
- percpu_up_read(&bdev->bd_block_size_semaphore);
-
blk_finish_plug(&plug);
-
return ret;
}
EXPORT_SYMBOL_GPL(blkdev_aio_write);
-static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
-{
- int ret;
- struct block_device *bdev = I_BDEV(file->f_mapping->host);
-
- percpu_down_read(&bdev->bd_block_size_semaphore);
-
- ret = generic_file_mmap(file, vma);
-
- percpu_up_read(&bdev->bd_block_size_semaphore);
-
- return ret;
-}
-
-static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
- struct pipe_inode_info *pipe, size_t len,
- unsigned int flags)
-{
- ssize_t ret;
- struct block_device *bdev = I_BDEV(file->f_mapping->host);
-
- percpu_down_read(&bdev->bd_block_size_semaphore);
-
- ret = generic_file_splice_read(file, ppos, pipe, len, flags);
-
- percpu_up_read(&bdev->bd_block_size_semaphore);
-
- return ret;
-}
-
-static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
- struct file *file, loff_t *ppos, size_t len,
- unsigned int flags)
+static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
- ssize_t ret;
- struct block_device *bdev = I_BDEV(file->f_mapping->host);
-
- percpu_down_read(&bdev->bd_block_size_semaphore);
-
- ret = generic_file_splice_write(pipe, file, ppos, len, flags);
+ struct file *file = iocb->ki_filp;
+ struct inode *bd_inode = file->f_mapping->host;
+ loff_t size = i_size_read(bd_inode);
- percpu_up_read(&bdev->bd_block_size_semaphore);
+ if (pos >= size)
+ return 0;
- return ret;
+ size -= pos;
+ if (size < INT_MAX)
+ nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size);
+ return generic_file_aio_read(iocb, iov, nr_segs, pos);
}
-
/*
* Try to release a page associated with block device when the system
* is under memory pressure.
@@ -1724,16 +1590,16 @@ const struct file_operations def_blk_fops = {
.llseek = block_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = blkdev_aio_read,
+ .aio_read = blkdev_aio_read,
.aio_write = blkdev_aio_write,
- .mmap = blkdev_mmap,
+ .mmap = generic_file_mmap,
.fsync = blkdev_fsync,
.unlocked_ioctl = block_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
- .splice_read = blkdev_splice_read,
- .splice_write = blkdev_splice_write,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
diff --git a/fs/buffer.c b/fs/buffer.c
index b5f044283edb..ec0aca8ba6bf 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -911,6 +911,18 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
attach_page_buffers(page, head);
}
+static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
+{
+ sector_t retval = ~((sector_t)0);
+ loff_t sz = i_size_read(bdev->bd_inode);
+
+ if (sz) {
+ unsigned int sizebits = blksize_bits(size);
+ retval = (sz >> sizebits);
+ }
+ return retval;
+}
+
/*
* Initialise the state of a blockdev page's buffers.
*/
@@ -921,7 +933,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));
+ sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size);
do {
if (!buffer_mapped(bh)) {
@@ -1553,6 +1565,28 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
EXPORT_SYMBOL(unmap_underlying_metadata);
/*
+ * Size is a power-of-two in the range 512..PAGE_SIZE,
+ * and the case we care about most is PAGE_SIZE.
+ *
+ * So this *could* possibly be written with those
+ * constraints in mind (relevant mostly if some
+ * architecture has a slow bit-scan instruction)
+ */
+static inline int block_size_bits(unsigned int blocksize)
+{
+ return ilog2(blocksize);
+}
+
+static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
+{
+ BUG_ON(!PageLocked(page));
+
+ if (!page_has_buffers(page))
+ create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits), b_state);
+ return page_buffers(page);
+}
+
+/*
* NOTE! All mapped/uptodate combinations are valid:
*
* Mapped Uptodate Meaning
@@ -1589,19 +1623,13 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
sector_t block;
sector_t last_block;
struct buffer_head *bh, *head;
- const unsigned blocksize = 1 << inode->i_blkbits;
+ unsigned int blocksize, bbits;
int nr_underway = 0;
int write_op = (wbc->sync_mode == WB_SYNC_ALL ?
WRITE_SYNC : WRITE);
- BUG_ON(!PageLocked(page));
-
- last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
-
- if (!page_has_buffers(page)) {
- create_empty_buffers(page, blocksize,
+ head = create_page_buffers(page, inode,
(1 << BH_Dirty)|(1 << BH_Uptodate));
- }
/*
* Be very careful. We have no exclusion from __set_page_dirty_buffers
@@ -1613,9 +1641,12 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
* handle that here by just cleaning them.
*/
- block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- head = page_buffers(page);
bh = head;
+ blocksize = bh->b_size;
+ bbits = block_size_bits(blocksize);
+
+ block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
+ last_block = (i_size_read(inode) - 1) >> bbits;
/*
* Get all the dirty buffers mapped to disk addresses and
@@ -1806,12 +1837,10 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
BUG_ON(to > PAGE_CACHE_SIZE);
BUG_ON(from > to);
- blocksize = 1 << inode->i_blkbits;
- if (!page_has_buffers(page))
- create_empty_buffers(page, blocksize, 0);
- head = page_buffers(page);
+ head = create_page_buffers(page, inode, 0);
+ blocksize = head->b_size;
+ bbits = block_size_bits(blocksize);
- bbits = inode->i_blkbits;
block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
for(bh = head, block_start = 0; bh != head || !block_start;
@@ -1881,11 +1910,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
unsigned blocksize;
struct buffer_head *bh, *head;
- blocksize = 1 << inode->i_blkbits;
+ bh = head = page_buffers(page);
+ blocksize = bh->b_size;
- for(bh = head = page_buffers(page), block_start = 0;
- bh != head || !block_start;
- block_start=block_end, bh = bh->b_this_page) {
+ block_start = 0;
+ do {
block_end = block_start + blocksize;
if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh))
@@ -1895,7 +1924,10 @@ static int __block_commit_write(struct inode *inode, struct page *page,
mark_buffer_dirty(bh);
}
clear_buffer_new(bh);
- }
+
+ block_start = block_end;
+ bh = bh->b_this_page;
+ } while (bh != head);
/*
* If this is a partial write which happened to make all buffers
@@ -2020,7 +2052,6 @@ EXPORT_SYMBOL(generic_write_end);
int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
unsigned long from)
{
- struct inode *inode = page->mapping->host;
unsigned block_start, block_end, blocksize;
unsigned to;
struct buffer_head *bh, *head;
@@ -2029,13 +2060,13 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
if (!page_has_buffers(page))
return 0;
- blocksize = 1 << inode->i_blkbits;
+ head = page_buffers(page);
+ blocksize = head->b_size;
to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count);
to = from + to;
if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)
return 0;
- head = page_buffers(page);
bh = head;
block_start = 0;
do {
@@ -2068,18 +2099,16 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
struct inode *inode = page->mapping->host;
sector_t iblock, lblock;
struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
- unsigned int blocksize;
+ unsigned int blocksize, bbits;
int nr, i;
int fully_mapped = 1;
- BUG_ON(!PageLocked(page));
- blocksize = 1 << inode->i_blkbits;
- if (!page_has_buffers(page))
- create_empty_buffers(page, blocksize, 0);
- head = page_buffers(page);
+ head = create_page_buffers(page, inode, 0);
+ blocksize = head->b_size;
+ bbits = block_size_bits(blocksize);
- iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits;
+ iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
+ lblock = (i_size_read(inode)+blocksize-1) >> bbits;
bh = head;
nr = 0;
i = 0;
@@ -2864,6 +2893,55 @@ static void end_bio_bh_io_sync(struct bio *bio, int err)
bio_put(bio);
}
+/*
+ * This allows us to do IO even on the odd last sectors
+ * of a device, even if the bh block size is some multiple
+ * of the physical sector size.
+ *
+ * We'll just truncate the bio to the size of the device,
+ * and clear the end of the buffer head manually.
+ *
+ * Truly out-of-range accesses will turn into actual IO
+ * errors, this only handles the "we need to be able to
+ * do IO at the final sector" case.
+ */
+static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
+{
+ sector_t maxsector;
+ unsigned bytes;
+
+ maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9;
+ if (!maxsector)
+ return;
+
+ /*
+ * If the *whole* IO is past the end of the device,
+ * let it through, and the IO layer will turn it into
+ * an EIO.
+ */
+ if (unlikely(bio->bi_sector >= maxsector))
+ return;
+
+ maxsector -= bio->bi_sector;
+ bytes = bio->bi_size;
+ if (likely((bytes >> 9) <= maxsector))
+ return;
+
+ /* Uhhuh. We've got a bh that straddles the device size! */
+ bytes = maxsector << 9;
+
+ /* Truncate the bio.. */
+ bio->bi_size = bytes;
+ bio->bi_io_vec[0].bv_len = bytes;
+
+ /* ..and clear the end of the buffer for reads */
+ if ((rw & RW_MASK) == READ) {
+ void *kaddr = kmap_atomic(bh->b_page);
+ memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes);
+ kunmap_atomic(kaddr);
+ }
+}
+
int submit_bh(int rw, struct buffer_head * bh)
{
struct bio *bio;
@@ -2900,6 +2978,9 @@ int submit_bh(int rw, struct buffer_head * bh)
bio->bi_end_io = end_bio_bh_io_sync;
bio->bi_private = bh;
+ /* Take care of bh's that straddle the end of the device */
+ guard_bh_eod(rw, bio, bh);
+
bio_get(bio);
submit_bio(rw, bio);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index edb25b4bbb95..70b6f4c3a0c1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1794,7 +1794,6 @@ static int cifs_writepages(struct address_space *mapping,
struct TCP_Server_Info *server;
struct page *page;
int rc = 0;
- loff_t isize = i_size_read(mapping->host);
/*
* If wsize is smaller than the page cache size, default to writing
@@ -1899,7 +1898,7 @@ retry:
*/
set_page_writeback(page);
- if (page_offset(page) >= isize) {
+ if (page_offset(page) >= i_size_read(mapping->host)) {
done = true;
unlock_page(page);
end_page_writeback(page);
@@ -1932,7 +1931,8 @@ retry:
wdata->offset = page_offset(wdata->pages[0]);
wdata->pagesz = PAGE_CACHE_SIZE;
wdata->tailsz =
- min(isize - page_offset(wdata->pages[nr_pages - 1]),
+ min(i_size_read(mapping->host) -
+ page_offset(wdata->pages[nr_pages - 1]),
(loff_t)PAGE_CACHE_SIZE);
wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
wdata->tailsz;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f9b5d3d6cf33..1c576e871366 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
dentry = d_lookup(parent, name);
if (dentry) {
+ int err;
inode = dentry->d_inode;
/* update inode in place if i_ino didn't change */
if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
cifs_fattr_to_inode(inode, fattr);
return dentry;
}
- d_drop(dentry);
+ err = d_invalidate(dentry);
dput(dentry);
+ if (err)
+ return NULL;
}
dentry = d_alloc(parent, name);
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 56cc4be87807..34cea2798333 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -766,7 +766,6 @@ smb_set_file_info(struct inode *inode, const char *full_path,
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = NULL;
struct cifs_tcon *tcon;
- FILE_BASIC_INFO info_buf;
/* if the file is already open for write, just use that fileid */
open_file = find_writable_file(cinode, true);
@@ -817,7 +816,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
netpid = current->tgid;
set_via_filehandle:
- rc = CIFSSMBSetFileInfo(xid, tcon, &info_buf, netfid, netpid);
+ rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid);
if (!rc)
cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b607d92cdf24..153bb1e42e63 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -59,7 +59,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- inode->i_private = NULL;
/* directory inodes start off with i_nlink == 2
* (for "." entry) */
diff --git a/fs/direct-io.c b/fs/direct-io.c
index f86c720dba0e..cf5b44b10c67 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -540,6 +540,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
sector_t fs_endblk; /* Into file, in filesystem-sized blocks */
unsigned long fs_count; /* Number of filesystem-sized blocks */
int create;
+ unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
/*
* If there was a memory error and we've overwritten all the
@@ -554,7 +555,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
fs_count = fs_endblk - fs_startblk + 1;
map_bh->b_state = 0;
- map_bh->b_size = fs_count << dio->inode->i_blkbits;
+ map_bh->b_size = fs_count << i_blkbits;
/*
* For writes inside i_size on a DIO_SKIP_HOLES filesystem we
@@ -1053,7 +1054,8 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
int seg;
size_t size;
unsigned long addr;
- unsigned blkbits = inode->i_blkbits;
+ unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
+ unsigned blkbits = i_blkbits;
unsigned blocksize_mask = (1 << blkbits) - 1;
ssize_t retval = -EINVAL;
loff_t end = offset;
@@ -1149,7 +1151,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
dio->inode = inode;
dio->rw = rw;
sdio.blkbits = blkbits;
- sdio.blkfactor = inode->i_blkbits - blkbits;
+ sdio.blkfactor = i_blkbits - blkbits;
sdio.block_in_file = offset >> blkbits;
sdio.get_block = get_block;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 7320a66e958f..22548f56197b 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
end = start + (range->len >> sb->s_blocksize_bits) - 1;
minlen = range->minlen >> sb->s_blocksize_bits;
- if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
- unlikely(start >= max_blks))
+ if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
+ start >= max_blks ||
+ range->len < sb->s_blocksize)
return -EINVAL;
if (end >= max_blks)
end = max_blks - 1;
diff --git a/fs/file.c b/fs/file.c
index 708d997a7748..eff23162485f 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
struct fdtable *fdt;
/* exec unshares first */
- BUG_ON(atomic_read(&files->count) != 1);
spin_lock(&files->file_lock);
for (i = 0; ; i++) {
unsigned long set;
@@ -995,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n,
const void *p)
{
struct fdtable *fdt;
- struct file *file;
int res = 0;
if (!files)
return 0;
spin_lock(&files->file_lock);
- fdt = files_fdtable(files);
- while (!res && n < fdt->max_fds) {
- file = rcu_dereference_check_fdtable(files, fdt->fd[n++]);
- if (file)
- res = f(p, file, n);
+ for (fdt = files_fdtable(files); n < fdt->max_fds; n++) {
+ struct file *file;
+ file = rcu_dereference_check_fdtable(files, fdt->fd[n]);
+ if (!file)
+ continue;
+ res = f(p, file, n);
+ if (res)
+ break;
}
spin_unlock(&files->file_lock);
return res;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 51ea267d444c..3e3422f7f0a4 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -228,6 +228,8 @@ static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
static void inode_sync_complete(struct inode *inode)
{
inode->i_state &= ~I_SYNC;
+ /* If inode is clean an unused, put it into LRU now... */
+ inode_add_lru(inode);
/* Waiters must see I_SYNC cleared before being woken up */
smp_mb();
wake_up_bit(&inode->i_state, __I_SYNC);
diff --git a/fs/inode.c b/fs/inode.c
index b03c71957246..64999f144153 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -408,6 +408,19 @@ static void inode_lru_list_add(struct inode *inode)
spin_unlock(&inode->i_sb->s_inode_lru_lock);
}
+/*
+ * Add inode to LRU if needed (inode is unused and clean).
+ *
+ * Needs inode->i_lock held.
+ */
+void inode_add_lru(struct inode *inode)
+{
+ if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
+ !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+ inode_lru_list_add(inode);
+}
+
+
static void inode_lru_list_del(struct inode *inode)
{
spin_lock(&inode->i_sb->s_inode_lru_lock);
@@ -1390,8 +1403,7 @@ static void iput_final(struct inode *inode)
if (!drop && (sb->s_flags & MS_ACTIVE)) {
inode->i_state |= I_REFERENCED;
- if (!(inode->i_state & (I_DIRTY|I_SYNC)))
- inode_lru_list_add(inode);
+ inode_add_lru(inode);
spin_unlock(&inode->i_lock);
return;
}
diff --git a/fs/internal.h b/fs/internal.h
index 916b7cbf3e3e..2f6af7f645eb 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -110,6 +110,7 @@ extern int open_check_o_direct(struct file *f);
* inode.c
*/
extern spinlock_t inode_sb_list_lock;
+extern void inode_add_lru(struct inode *inode);
/*
* fs-writeback.c
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 78b7f84241d4..7f5120bf0ec2 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1961,7 +1961,9 @@ retry:
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
spin_unlock(&journal->j_state_lock);
+ unlock_buffer(bh);
log_wait_commit(journal, tid);
+ lock_buffer(bh);
goto retry;
}
/*
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 60ef3fb707ff..1506673c087e 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
struct page *pg;
struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+ struct jffs2_raw_inode ri;
+ uint32_t alloc_len = 0;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
uint32_t pageofs = index << PAGE_CACHE_SHIFT;
int ret = 0;
+ jffs2_dbg(1, "%s()\n", __func__);
+
+ if (pageofs > inode->i_size) {
+ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+ if (ret)
+ return ret;
+ }
+
+ mutex_lock(&f->sem);
pg = grab_cache_page_write_begin(mapping, index, flags);
- if (!pg)
+ if (!pg) {
+ if (alloc_len)
+ jffs2_complete_reservation(c);
+ mutex_unlock(&f->sem);
return -ENOMEM;
+ }
*pagep = pg;
- jffs2_dbg(1, "%s()\n", __func__);
-
- if (pageofs > inode->i_size) {
+ if (alloc_len) {
/* Make new hole frag from old EOF to new page */
- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
- struct jffs2_raw_inode ri;
struct jffs2_full_dnode *fn;
- uint32_t alloc_len;
jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
(unsigned int)inode->i_size, pageofs);
- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
- if (ret)
- goto out_page;
-
- mutex_lock(&f->sem);
memset(&ri, 0, sizeof(ri));
ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
if (IS_ERR(fn)) {
ret = PTR_ERR(fn);
jffs2_complete_reservation(c);
- mutex_unlock(&f->sem);
goto out_page;
}
ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn);
jffs2_complete_reservation(c);
- mutex_unlock(&f->sem);
goto out_page;
}
jffs2_complete_reservation(c);
inode->i_size = pageofs;
- mutex_unlock(&f->sem);
}
/*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
* case of a short-copy.
*/
if (!PageUptodate(pg)) {
- mutex_lock(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg);
- mutex_unlock(&f->sem);
if (ret)
goto out_page;
}
+ mutex_unlock(&f->sem);
jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
return ret;
out_page:
unlock_page(pg);
page_cache_release(pg);
+ mutex_unlock(&f->sem);
return ret;
}
diff --git a/fs/namei.c b/fs/namei.c
index 937f9d50c84b..5f4cdf3ad913 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
if (!len)
return ERR_PTR(-EACCES);
+ if (unlikely(name[0] == '.')) {
+ if (len < 2 || (len == 2 && name[1] == '.'))
+ return ERR_PTR(-EACCES);
+ }
+
while (len--) {
c = *(const unsigned char *)name++;
if (c == '/' || c == '\0')
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ce8cb926526b..b9e66b7e0c14 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
nfs_refresh_inode(dentry->d_inode, entry->fattr);
goto out;
} else {
- d_drop(dentry);
+ if (d_invalidate(dentry) != 0)
+ goto out;
dput(dentry);
}
}
@@ -1100,6 +1101,8 @@ out_set_verifier:
out_zap_parent:
nfs_zap_caches(dir);
out_bad:
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
nfs_mark_for_revalidate(dir);
if (inode && S_ISDIR(inode->i_mode)) {
/* Purge readdir caches. */
@@ -1112,8 +1115,6 @@ out_zap_parent:
shrink_dcache_parent(dentry);
}
d_drop(dentry);
- nfs_free_fattr(fattr);
- nfs_free_fhandle(fhandle);
dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
__func__, dentry->d_parent->d_name.name,
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 721d692fa8d4..6fcaeb8c902e 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
if (ret)
goto out_close_fd;
- fd_install(fd, f);
+ if (fd != FAN_NOFD)
+ fd_install(fd, f);
return fanotify_event_metadata.event_len;
out_close_fd:
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 3c231adf8450..9e28356a959a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1877,8 +1877,9 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
if (!vma)
goto out_no_vma;
- result = proc_map_files_instantiate(dir, dentry, task,
- (void *)(unsigned long)vma->vm_file->f_mode);
+ if (vma->vm_file)
+ result = proc_map_files_instantiate(dir, dentry, task,
+ (void *)(unsigned long)vma->vm_file->f_mode);
out_no_vma:
up_read(&mm->mmap_sem);
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index f27f01a98aa2..d83736fbc26c 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
BUG_ON(!th->t_trans_id);
- dquot_initialize(inode);
+ reiserfs_write_unlock(inode->i_sb);
err = dquot_alloc_inode(inode);
+ reiserfs_write_lock(inode->i_sb);
if (err)
goto out_end_trans;
if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
out_end_trans:
journal_end(th, th->t_super, th->t_blocks_allocated);
+ reiserfs_write_unlock(inode->i_sb);
/* Drop can be outside and it needs more credits so it's better to have it outside */
dquot_drop(inode);
+ reiserfs_write_lock(inode->i_sb);
inode->i_flags |= S_NOQUOTA;
make_bad_inode(inode);
@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
/* must be turned off for recursive notify_change calls */
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
- depth = reiserfs_write_lock_once(inode->i_sb);
if (is_quota_modification(inode, attr))
dquot_initialize(inode);
-
+ depth = reiserfs_write_lock_once(inode->i_sb);
if (attr->ia_valid & ATTR_SIZE) {
/* version 2 items will be caught by the s_maxbytes check
** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
error = journal_begin(&th, inode->i_sb, jbegin_count);
if (error)
goto out;
+ reiserfs_write_unlock_once(inode->i_sb, depth);
error = dquot_transfer(inode, attr);
+ depth = reiserfs_write_lock_once(inode->i_sb);
if (error) {
journal_end(&th, inode->i_sb, jbegin_count);
goto out;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index f8afa4b162b8..2f40a4c70a4d 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
key2type(&(key->on_disk_key)));
#endif
+ reiserfs_write_unlock(inode->i_sb);
retval = dquot_alloc_space_nodirty(inode, pasted_size);
+ reiserfs_write_lock(inode->i_sb);
if (retval) {
pathrelse(search_path);
return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
"reiserquota insert_item(): allocating %u id=%u type=%c",
quota_bytes, inode->i_uid, head2type(ih));
#endif
+ reiserfs_write_unlock(inode->i_sb);
/* We can't dirty inode here. It would be immediately written but
* appropriate stat item isn't inserted yet... */
retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+ reiserfs_write_lock(inode->i_sb);
if (retval) {
pathrelse(path);
return retval;
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 1078ae179993..418bdc3a57da 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
retval = remove_save_link_only(s, &save_link_key, 0);
continue;
}
+ reiserfs_write_unlock(s);
dquot_initialize(inode);
+ reiserfs_write_lock(s);
if (truncate && S_ISDIR(inode->i_mode)) {
/* We got a truncate request for a dir which is impossible.
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
kfree(qf_names[i]);
#endif
err = -EINVAL;
- goto out_err;
+ goto out_unlock;
}
#ifdef CONFIG_QUOTA
handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (blocks) {
err = reiserfs_resize(s, blocks);
if (err != 0)
- goto out_err;
+ goto out_unlock;
}
if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
/* it is read-only already */
goto out_ok;
+ /*
+ * Drop write lock. Quota will retake it when needed and lock
+ * ordering requires calling dquot_suspend() without it.
+ */
+ reiserfs_write_unlock(s);
err = dquot_suspend(s, -1);
if (err < 0)
goto out_err;
+ reiserfs_write_lock(s);
/* try to remount file system with read-only permissions */
if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
err = journal_begin(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
/* Mounting a rw partition read-only. */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (reiserfs_is_journal_aborted(journal)) {
err = journal->j_errno;
- goto out_err;
+ goto out_unlock;
}
handle_data_mode(s, mount_options);
@@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
err = journal_begin(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
/* Mount a partition which is read-only, read-write */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
SB_JOURNAL(s)->j_must_wait = 1;
err = journal_end(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
if (!(*mount_flags & MS_RDONLY)) {
+ /*
+ * Drop write lock. Quota will retake it when needed and lock
+ * ordering requires calling dquot_resume() without it.
+ */
+ reiserfs_write_unlock(s);
dquot_resume(s, -1);
+ reiserfs_write_lock(s);
finish_unfinished(s);
reiserfs_xattr_init(s, *mount_flags);
}
@@ -1455,9 +1469,10 @@ out_ok:
reiserfs_write_unlock(s);
return 0;
+out_unlock:
+ reiserfs_write_unlock(s);
out_err:
kfree(new_opts);
- reiserfs_write_unlock(s);
return err;
}
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (ret)
goto out;
+ reiserfs_write_unlock(dquot->dq_sb);
ret = dquot_commit(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (ret)
goto out;
+ reiserfs_write_unlock(dquot->dq_sb);
ret = dquot_acquire(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
ret =
journal_begin(&th, dquot->dq_sb,
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ reiserfs_write_unlock(dquot->dq_sb);
if (ret) {
/* Release dquot anyway to avoid endless cycle in dqput() */
dquot_release(dquot);
goto out;
}
ret = dquot_release(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
reiserfs_write_unlock(dquot->dq_sb);
+out:
return ret;
}
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
ret = journal_begin(&th, sb, 2);
if (ret)
goto out;
+ reiserfs_write_unlock(sb);
ret = dquot_commit_info(sb, type);
+ reiserfs_write_lock(sb);
err = journal_end(&th, sb, 2);
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(sb);
return ret;
}
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
struct reiserfs_transaction_handle th;
int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
- if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
- return -EINVAL;
+ reiserfs_write_lock(sb);
+ if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+ err = -EINVAL;
+ goto out;
+ }
/* Quotafile not on the same filesystem? */
if (path->dentry->d_sb != sb) {
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
if (err)
goto out;
}
- err = dquot_quota_on(sb, type, format_id, path);
+ reiserfs_write_unlock(sb);
+ return dquot_quota_on(sb, type, format_id, path);
out:
+ reiserfs_write_unlock(sb);
return err;
}
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
tmp_bh.b_state = 0;
+ reiserfs_write_lock(sb);
err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+ reiserfs_write_unlock(sb);
if (err)
goto out;
if (offset || tocopy != sb->s_blocksize)
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
flush_dcache_page(bh->b_page);
set_buffer_uptodate(bh);
unlock_buffer(bh);
+ reiserfs_write_lock(sb);
reiserfs_prepare_for_journal(sb, bh, 1);
journal_mark_dirty(current->journal_info, sb, bh);
if (!journal_quota)
reiserfs_add_ordered_list(inode, bh);
+ reiserfs_write_unlock(sb);
brelse(bh);
offset = 0;
towrite -= tocopy;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 00012e31829d..602f56db0442 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -485,8 +485,8 @@ const struct file_operations sysfs_file_operations = {
.poll = sysfs_poll,
};
-int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
- const void **pns)
+static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
+ const void **pns)
{
struct sysfs_dirent *dir_sd = kobj->sd;
const struct sysfs_ops *ops;
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index e562dd43f41f..e57e2daa357c 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
*
* The fix is two passes across the ioend list - one to start writeback on the
* buffer_heads, and then submit them for I/O on the second pass.
+ *
+ * If @fail is non-zero, it means that we have a situation where some part of
+ * the submission process has failed after we have marked paged for writeback
+ * and unlocked them. In this situation, we need to fail the ioend chain rather
+ * than submit it to IO. This typically only happens on a filesystem shutdown.
*/
STATIC void
xfs_submit_ioend(
struct writeback_control *wbc,
- xfs_ioend_t *ioend)
+ xfs_ioend_t *ioend,
+ int fail)
{
xfs_ioend_t *head = ioend;
xfs_ioend_t *next;
@@ -506,6 +512,18 @@ xfs_submit_ioend(
next = ioend->io_list;
bio = NULL;
+ /*
+ * If we are failing the IO now, just mark the ioend with an
+ * error and finish it. This will run IO completion immediately
+ * as there is only one reference to the ioend at this point in
+ * time.
+ */
+ if (fail) {
+ ioend->io_error = -fail;
+ xfs_finish_ioend(ioend);
+ continue;
+ }
+
for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
if (!bio) {
@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
xfs_start_page_writeback(page, 1, count);
- if (ioend && imap_valid) {
+ /* if there is no IO to be submitted for this page, we are done */
+ if (!ioend)
+ return 0;
+
+ ASSERT(iohead);
+
+ /*
+ * Any errors from this point onwards need tobe reported through the IO
+ * completion path as we have marked the initial page as under writeback
+ * and unlocked it.
+ */
+ if (imap_valid) {
xfs_off_t end_index;
end_index = imap.br_startoff + imap.br_blockcount;
@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
wbc, end_index);
}
- if (iohead) {
- /*
- * Reserve log space if we might write beyond the on-disk
- * inode size.
- */
- if (ioend->io_type != XFS_IO_UNWRITTEN &&
- xfs_ioend_is_append(ioend)) {
- err = xfs_setfilesize_trans_alloc(ioend);
- if (err)
- goto error;
- }
- xfs_submit_ioend(wbc, iohead);
- }
+ /*
+ * Reserve log space if we might write beyond the on-disk inode size.
+ */
+ err = 0;
+ if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
+ err = xfs_setfilesize_trans_alloc(ioend);
+
+ xfs_submit_ioend(wbc, iohead, err);
return 0;
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index d330111ca738..70eec1829776 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
leaf2 = blk2->bp->b_addr;
ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+ ASSERT(leaf2->hdr.count == 0);
args = state->args;
trace_xfs_attr_leaf_rebalance(args);
@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
* I assert that since all callers pass in an empty
* second buffer, this code should never execute.
*/
+ ASSERT(0);
/*
* Figure the total bytes to be added to the destination leaf.
@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
args->index2 = 0;
args->blkno2 = blk2->blkno;
} else {
+ /*
+ * On a double leaf split, the original attr location
+ * is already stored in blkno2/index2, so don't
+ * overwrite it overwise we corrupt the tree.
+ */
blk2->index = blk1->index
- be16_to_cpu(leaf1->hdr.count);
- args->index = args->index2 = blk2->index;
- args->blkno = args->blkno2 = blk2->blkno;
+ args->index = blk2->index;
+ args->blkno = blk2->blkno;
+ if (!state->extravalid) {
+ /*
+ * set the new attr location to match the old
+ * one and let the higher level split code
+ * decide where in the leaf to place it.
+ */
+ args->index2 = blk2->index;
+ args->blkno2 = blk2->blkno;
+ }
}
} else {
ASSERT(state->inleaf == 1);
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 933b7930b863..4b0b8dd1b7b0 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
{
xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private;
- xfs_buf_ioerror(bp, -error);
+ /*
+ * don't overwrite existing errors - otherwise we can lose errors on
+ * buffers that require multiple bios to complete.
+ */
+ if (!bp->b_error)
+ xfs_buf_ioerror(bp, -error);
- if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+ if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
_xfs_buf_ioend(bp, 1);
@@ -1279,6 +1284,11 @@ next_chunk:
if (size)
goto next_chunk;
} else {
+ /*
+ * This is guaranteed not to be the last io reference count
+ * because the caller (xfs_buf_iorequest) holds a count itself.
+ */
+ atomic_dec(&bp->b_io_remaining);
xfs_buf_ioerror(bp, EIO);
bio_put(bio);
}
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 03f14856bd09..0943457e0fa5 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -241,6 +241,7 @@
*****************************************************************************/
#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */
+#define ACPI_DB_LINE_BUFFER_SIZE 512
#define ACPI_DEBUGGER_COMMAND_PROMPT '-'
#define ACPI_DEBUGGER_EXECUTE_PROMPT '%'
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 19503449814f..6c3890e02140 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -122,7 +122,7 @@
#define AE_CODE_TBL_MAX 0x0005
/*
- * AML exceptions. These are caused by problems with
+ * AML exceptions. These are caused by problems with
* the actual AML byte stream
*/
#define AE_AML_BAD_OPCODE (acpi_status) (0x0001 | AE_CODE_AML)
diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h
index 745dd24e3cb5..7665df663284 100644
--- a/include/acpi/acnames.h
+++ b/include/acpi/acnames.h
@@ -50,6 +50,7 @@
#define METHOD_NAME__HID "_HID"
#define METHOD_NAME__CID "_CID"
#define METHOD_NAME__UID "_UID"
+#define METHOD_NAME__SUB "_SUB"
#define METHOD_NAME__ADR "_ADR"
#define METHOD_NAME__INI "_INI"
#define METHOD_NAME__STA "_STA"
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0daa0fbd8654..7ced5dc20dd3 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -144,12 +144,11 @@ struct acpi_device_flags {
u32 bus_address:1;
u32 removable:1;
u32 ejectable:1;
- u32 lockable:1;
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
u32 eject_pending:1;
- u32 reserved:23;
+ u32 reserved:24;
};
/* File System */
@@ -180,6 +179,7 @@ struct acpi_device_pnp {
acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */
union acpi_object *str_obj; /* unicode string for _STR method */
+ unsigned long sun; /* _SUN */
};
#define acpi_device_bid(d) ((d)->pnp.bus_id)
@@ -201,6 +201,7 @@ struct acpi_device_power_flags {
struct acpi_device_power_state {
struct {
u8 valid:1;
+ u8 os_accessible:1;
u8 explicit_set:1; /* _PSx present? */
u8 reserved:6;
} flags;
@@ -339,6 +340,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
unsigned long long *sta);
int acpi_bus_get_status(struct acpi_device *device);
int acpi_bus_set_power(acpi_handle handle, int state);
+int acpi_device_set_power(struct acpi_device *device, int state);
int acpi_bus_update_power(acpi_handle handle, int *state_p);
bool acpi_bus_power_manageable(acpi_handle handle);
bool acpi_bus_can_wakeup(acpi_handle handle);
@@ -410,36 +412,100 @@ acpi_handle acpi_get_child(acpi_handle, u64);
int acpi_is_root_bridge(acpi_handle);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
-#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
+#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
#ifdef CONFIG_PM
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler, void *context);
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler);
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+ u32 target_state, int d_max_in, int *d_min_p);
int acpi_pm_device_sleep_state(struct device *, int *, int);
#else
-static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler,
+ void *context)
+{
+ return AE_SUPPORT;
+}
+static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+ acpi_notify_handler handler)
+{
+ return AE_SUPPORT;
+}
+static inline int __acpi_device_power_state(int m, int *p)
{
if (p)
*p = ACPI_STATE_D0;
return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
}
+static inline int acpi_device_power_state(struct device *dev,
+ struct acpi_device *adev,
+ u32 target_state, int d_max_in,
+ int *d_min_p)
+{
+ return __acpi_device_power_state(d_max_in, d_min_p);
+}
+static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+{
+ return __acpi_device_power_state(m, p);
+}
#endif
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_RUNTIME
+int __acpi_device_run_wake(struct acpi_device *, bool);
int acpi_pm_device_run_wake(struct device *, bool);
-int acpi_pm_device_sleep_wake(struct device *, bool);
#else
+static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en)
+{
+ return -ENODEV;
+}
static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
{
return -ENODEV;
}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int __acpi_device_sleep_wake(struct acpi_device *, u32, bool);
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
+static inline int __acpi_device_sleep_wake(struct acpi_device *adev,
+ u32 target_state, bool enable)
+{
+ return -ENODEV;
+}
static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
{
return -ENODEV;
}
#endif
+#ifdef CONFIG_ACPI_SLEEP
+u32 acpi_target_system_state(void);
+#else
+static inline u32 acpi_target_system_state(void) { return ACPI_STATE_S0; }
+#endif
+
+static inline bool acpi_device_power_manageable(struct acpi_device *adev)
+{
+ return adev->flags.power_manageable;
+}
+
+static inline bool acpi_device_can_wakeup(struct acpi_device *adev)
+{
+ return adev->wakeup.flags.valid;
+}
+
+static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
+{
+ return adev->power.states[ACPI_STATE_D3_COLD].flags.os_accessible;
+}
+
#else /* CONFIG_ACPI */
static inline int register_acpi_bus_type(void *bus) { return 0; }
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 1222ba93d80a..43152742b46f 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -1,7 +1,6 @@
-
/******************************************************************************
*
- * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These
+ * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These
* interfaces must be implemented by OSL to interface the
* ACPI components to the host operating system.
*
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 8b891dbead66..3d88395d4d6f 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -1,4 +1,3 @@
-
/******************************************************************************
*
* Name: acpixf.h - External interfaces to the ACPI subsystem
@@ -47,7 +46,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20120913
+#define ACPI_CA_VERSION 0x20121018
#include <acpi/acconfig.h>
#include <acpi/actypes.h>
@@ -178,8 +177,7 @@ acpi_status acpi_unload_table_id(acpi_owner_id id);
acpi_status
acpi_get_table_header(acpi_string signature,
- u32 instance,
- struct acpi_table_header *out_table_header);
+ u32 instance, struct acpi_table_header *out_table_header);
acpi_status
acpi_get_table_with_size(acpi_string signature,
@@ -190,8 +188,7 @@ acpi_get_table(acpi_string signature,
u32 instance, struct acpi_table_header **out_table);
acpi_status
-acpi_get_table_by_index(u32 table_index,
- struct acpi_table_header **out_table);
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table);
acpi_status
acpi_install_table_handler(acpi_tbl_handler handler, void *context);
@@ -274,7 +271,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_global_event_handler
- (ACPI_GBL_EVENT_HANDLER handler, void *context))
+ (acpi_gbl_event_handler handler, void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_fixed_event_handler(u32
@@ -300,10 +297,9 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
u32 gpe_number,
acpi_gpe_handler
address))
-acpi_status
-acpi_install_notify_handler(acpi_handle device,
- u32 handler_type,
- acpi_notify_handler handler, void *context);
+acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type,
+ acpi_notify_handler handler,
+ void *context);
acpi_status
acpi_remove_notify_handler(acpi_handle device,
diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h
index 8c61b5fe42a4..6585141e4b97 100644
--- a/include/acpi/actbl3.h
+++ b/include/acpi/actbl3.h
@@ -277,10 +277,10 @@ struct acpi_table_gtdt {
******************************************************************************/
#define ACPI_MPST_CHANNEL_INFO \
- u16 reserved1; \
u8 channel_id; \
- u8 reserved2; \
- u16 power_node_count;
+ u8 reserved1[3]; \
+ u16 power_node_count; \
+ u16 reserved2;
/* Main table */
@@ -304,9 +304,8 @@ struct acpi_mpst_power_node {
u32 length;
u64 range_address;
u64 range_length;
- u8 num_power_states;
- u8 num_physical_components;
- u16 reserved2;
+ u32 num_power_states;
+ u32 num_physical_components;
};
/* Values for Flags field above */
@@ -332,10 +331,11 @@ struct acpi_mpst_component {
struct acpi_mpst_data_hdr {
u16 characteristics_count;
+ u16 reserved;
};
struct acpi_mpst_power_data {
- u8 revision;
+ u8 structure_id;
u8 flags;
u16 reserved1;
u32 average_power;
@@ -356,10 +356,10 @@ struct acpi_mpst_shared {
u32 signature;
u16 pcc_command;
u16 pcc_status;
- u16 command_register;
- u16 status_register;
- u16 power_state_id;
- u16 power_node_id;
+ u32 command_register;
+ u32 status_register;
+ u32 power_state_id;
+ u32 power_node_id;
u64 energy_consumed;
u64 average_power;
};
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index a85bae968262..4f43f1fba132 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -453,10 +453,14 @@ typedef u64 acpi_integer;
#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i)
#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i)
+/* Optimizations for 4-character (32-bit) acpi_name manipulation */
+
#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
#define ACPI_COMPARE_NAME(a,b) (*ACPI_CAST_PTR (u32, (a)) == *ACPI_CAST_PTR (u32, (b)))
+#define ACPI_MOVE_NAME(dest,src) (*ACPI_CAST_PTR (u32, (dest)) = *ACPI_CAST_PTR (u32, (src)))
#else
#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE))
+#define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
#endif
/*******************************************************************************
@@ -796,11 +800,11 @@ typedef u8 acpi_adr_space_type;
/* Sleep function dispatch */
-typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state);
+typedef acpi_status(*acpi_sleep_function) (u8 sleep_state);
struct acpi_sleep_functions {
- ACPI_SLEEP_FUNCTION legacy_function;
- ACPI_SLEEP_FUNCTION extended_function;
+ acpi_sleep_function legacy_function;
+ acpi_sleep_function extended_function;
};
/*
@@ -922,7 +926,8 @@ struct acpi_system_info {
/*
* Types specific to the OS service interfaces
*/
-typedef u32(ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
+typedef u32
+ (ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
typedef void
(ACPI_SYSTEM_XFACE * acpi_osd_exec_callback) (void *context);
@@ -931,14 +936,15 @@ typedef void
* Various handlers and callback procedures
*/
typedef
-void (*ACPI_GBL_EVENT_HANDLER) (u32 event_type,
+void (*acpi_gbl_event_handler) (u32 event_type,
acpi_handle device,
u32 event_number, void *context);
#define ACPI_EVENT_TYPE_GPE 0
#define ACPI_EVENT_TYPE_FIXED 1
-typedef u32(*acpi_event_handler) (void *context);
+typedef
+u32(*acpi_event_handler) (void *context);
typedef
u32 (*acpi_gpe_handler) (acpi_handle gpe_device, u32 gpe_number, void *context);
@@ -1018,17 +1024,17 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
#define ACPI_UUID_LENGTH 16
-/* Structures used for device/processor HID, UID, CID */
+/* Structures used for device/processor HID, UID, CID, and SUB */
-struct acpica_device_id {
+struct acpi_pnp_device_id {
u32 length; /* Length of string + null */
char *string;
};
-struct acpica_device_id_list {
+struct acpi_pnp_device_id_list {
u32 count; /* Number of IDs in Ids array */
u32 list_size; /* Size of list, including ID strings */
- struct acpica_device_id ids[1]; /* ID array */
+ struct acpi_pnp_device_id ids[1]; /* ID array */
};
/*
@@ -1046,9 +1052,10 @@ struct acpi_device_info {
u8 lowest_dstates[5]; /* _sx_w values: 0xFF indicates not valid */
u32 current_status; /* _STA value */
u64 address; /* _ADR value */
- struct acpica_device_id hardware_id; /* _HID value */
- struct acpica_device_id unique_id; /* _UID value */
- struct acpica_device_id_list compatible_id_list; /* _CID list <must be last> */
+ struct acpi_pnp_device_id hardware_id; /* _HID value */
+ struct acpi_pnp_device_id unique_id; /* _UID value */
+ struct acpi_pnp_device_id subsystem_id; /* _SUB value */
+ struct acpi_pnp_device_id_list compatible_id_list; /* _CID list <must be last> */
};
/* Values for Flags field above (acpi_get_object_info) */
@@ -1061,11 +1068,12 @@ struct acpi_device_info {
#define ACPI_VALID_ADR 0x02
#define ACPI_VALID_HID 0x04
#define ACPI_VALID_UID 0x08
-#define ACPI_VALID_CID 0x10
-#define ACPI_VALID_SXDS 0x20
-#define ACPI_VALID_SXWS 0x40
+#define ACPI_VALID_SUB 0x10
+#define ACPI_VALID_CID 0x20
+#define ACPI_VALID_SXDS 0x40
+#define ACPI_VALID_SXWS 0x80
-/* Flags for _STA method */
+/* Flags for _STA return value (current_status above) */
#define ACPI_STA_DEVICE_PRESENT 0x01
#define ACPI_STA_DEVICE_ENABLED 0x02
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc6b8ba..20ca7663975f 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
#ifdef CONFIG_GPIOLIB
@@ -56,6 +57,8 @@ struct device_node;
* enabling module power and clock; may sleep
* @free: optional hook for chip-specific deactivation, such as
* disabling module power and clock; may sleep
+ * @get_direction: returns direction for signal "offset", 0=out, 1=in,
+ * (same as GPIOF_DIR_XXX), or negative error
* @direction_input: configures signal "offset" as input, or returns error
* @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero
@@ -100,7 +103,8 @@ struct gpio_chip {
unsigned offset);
void (*free)(struct gpio_chip *chip,
unsigned offset);
-
+ int (*get_direction)(struct gpio_chip *chip,
+ unsigned offset);
int (*direction_input)(struct gpio_chip *chip,
unsigned offset);
int (*get)(struct gpio_chip *chip,
@@ -134,6 +138,15 @@ struct gpio_chip {
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
+#ifdef CONFIG_PINCTRL
+ /*
+ * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+ * describe the actual pin range which they serve in an SoC. This
+ * information would be used by pinctrl subsystem to configure
+ * corresponding pins for gpio usage.
+ */
+ struct list_head pin_ranges;
+#endif
};
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@@ -257,4 +270,41 @@ static inline void gpio_unexport(unsigned gpio)
}
#endif /* CONFIG_GPIO_SYSFS */
+#ifdef CONFIG_PINCTRL
+
+/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+ struct list_head node;
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range range;
+};
+
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int gpio_offset, unsigned int pin_offset,
+ unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
+
+#else
+
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int gpio_offset, unsigned int pin_offset,
+ unsigned int npins)
+{
+ return 0;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_PINCTRL */
+
#endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index af1cbaf535ed..c5c35e629426 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -210,6 +210,7 @@
{0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
{0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
{0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
{0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 90be98981102..c33fa3ce9b7c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -25,7 +25,9 @@
#ifndef _LINUX_ACPI_H
#define _LINUX_ACPI_H
+#include <linux/errno.h>
#include <linux/ioport.h> /* for struct resource */
+#include <linux/device.h>
#ifdef CONFIG_ACPI
@@ -250,6 +252,26 @@ extern int pnpacpi_disabled;
#define PXM_INVAL (-1)
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+ struct resource *res);
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+ struct resource *res);
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+ struct resource *res);
+
+struct resource_list_entry {
+ struct list_head node;
+ struct resource res;
+};
+
+void acpi_dev_free_resource_list(struct list_head *list);
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+ int (*preproc)(struct acpi_resource *, void *),
+ void *preproc_data);
+
int acpi_check_resource_conflict(const struct resource *res);
int acpi_check_region(resource_size_t start, resource_size_t n,
@@ -257,10 +279,14 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
int acpi_resources_are_enforced(void);
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_HIBERNATION
void __init acpi_no_s4_hw_signature(void);
+#endif
+
+#ifdef CONFIG_PM_SLEEP
void __init acpi_old_suspend_ordering(void);
void __init acpi_nvs_nosave(void);
+void __init acpi_nvs_nosave_s3(void);
#endif /* CONFIG_PM_SLEEP */
struct acpi_osc_context {
@@ -364,6 +390,17 @@ extern int acpi_nvs_register(__u64 start, __u64 size);
extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
void *data);
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+ const struct device *dev);
+
+static inline bool acpi_driver_match_device(struct device *dev,
+ const struct device_driver *drv)
+{
+ return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+
+#define ACPI_PTR(_ptr) (_ptr)
+
#else /* !CONFIG_ACPI */
#define acpi_disabled 1
@@ -418,6 +455,22 @@ static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
return 0;
}
+struct acpi_device_id;
+
+static inline const struct acpi_device_id *acpi_match_device(
+ const struct acpi_device_id *ids, const struct device *dev)
+{
+ return NULL;
+}
+
+static inline bool acpi_driver_match_device(struct device *dev,
+ const struct device_driver *drv)
+{
+ return false;
+}
+
+#define ACPI_PTR(_ptr) (NULL)
+
#endif /* !CONFIG_ACPI */
#ifdef CONFIG_ACPI
@@ -430,4 +483,84 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
#define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
#endif
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM_RUNTIME)
+int acpi_dev_runtime_suspend(struct device *dev);
+int acpi_dev_runtime_resume(struct device *dev);
+int acpi_subsys_runtime_suspend(struct device *dev);
+int acpi_subsys_runtime_resume(struct device *dev);
+#else
+static inline int acpi_dev_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_dev_runtime_resume(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
+#endif
+
+#ifdef CONFIG_ACPI_SLEEP
+int acpi_dev_suspend_late(struct device *dev);
+int acpi_dev_resume_early(struct device *dev);
+int acpi_subsys_prepare(struct device *dev);
+int acpi_subsys_suspend_late(struct device *dev);
+int acpi_subsys_resume_early(struct device *dev);
+#else
+static inline int acpi_dev_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
+static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
+static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
+#endif
+
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
+int acpi_dev_pm_attach(struct device *dev, bool power_on);
+void acpi_dev_pm_detach(struct device *dev, bool power_off);
+#else
+static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+ return -ENODEV;
+}
+static inline void acpi_dev_pm_detach(struct device *dev, bool power_off) {}
+#endif
+
+#ifdef CONFIG_ACPI
+__printf(3, 4)
+void acpi_handle_printk(const char *level, acpi_handle handle,
+ const char *fmt, ...);
+#else /* !CONFIG_ACPI */
+static inline __printf(3, 4) void
+acpi_handle_printk(const char *level, void *handle, const char *fmt, ...) {}
+#endif /* !CONFIG_ACPI */
+
+/*
+ * acpi_handle_<level>: Print message with ACPI prefix and object path
+ *
+ * These interfaces acquire the global namespace mutex to obtain an object
+ * path. In interrupt context, it shows the object path as <n/a>.
+ */
+#define acpi_handle_emerg(handle, fmt, ...) \
+ acpi_handle_printk(KERN_EMERG, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_alert(handle, fmt, ...) \
+ acpi_handle_printk(KERN_ALERT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_crit(handle, fmt, ...) \
+ acpi_handle_printk(KERN_CRIT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_err(handle, fmt, ...) \
+ acpi_handle_printk(KERN_ERR, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_warn(handle, fmt, ...) \
+ acpi_handle_printk(KERN_WARNING, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_notice(handle, fmt, ...) \
+ acpi_handle_printk(KERN_NOTICE, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_info(handle, fmt, ...) \
+ acpi_handle_printk(KERN_INFO, handle, fmt, ##__VA_ARGS__)
+
+/* REVISIT: Support CONFIG_DYNAMIC_DEBUG when necessary */
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+#define acpi_handle_debug(handle, fmt, ...) \
+ acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__)
+#else
+#define acpi_handle_debug(handle, fmt, ...) \
+({ \
+ if (0) \
+ acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__); \
+ 0; \
+})
+#endif
+
#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
new file mode 100644
index 000000000000..91615a389b65
--- /dev/null
+++ b/include/linux/acpi_gpio.h
@@ -0,0 +1,19 @@
+#ifndef _LINUX_ACPI_GPIO_H_
+#define _LINUX_ACPI_GPIO_H_
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_GPIO_ACPI
+
+int acpi_get_gpio(char *path, int pin);
+
+#else /* CONFIG_GPIO_ACPI */
+
+static inline int acpi_get_gpio(char *path, int pin)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_GPIO_ACPI */
+
+#endif /* _LINUX_ACPI_GPIO_H_ */
diff --git a/include/linux/bug.h b/include/linux/bug.h
index aaac4bba6f5c..b1cf40de847e 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -15,6 +15,7 @@ struct pt_regs;
#define BUILD_BUG_ON_NOT_POWER_OF_2(n)
#define BUILD_BUG_ON_ZERO(e) (0)
#define BUILD_BUG_ON_NULL(e) ((void*)0)
+#define BUILD_BUG_ON_INVALID(e) (0)
#define BUILD_BUG_ON(condition)
#define BUILD_BUG() (0)
#else /* __CHECKER__ */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index f9f5e9eeb9dd..4989b8a7bed1 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -53,9 +53,18 @@ struct clk_hw;
* @disable: Disable the clock atomically. Called with enable_lock held.
* This function must not sleep.
*
- * @recalc_rate Recalculate the rate of this clock, by quering hardware. The
+ * @is_enabled: Queries the hardware to determine if the clock is enabled.
+ * This function must not sleep. Optional, if this op is not
+ * set then the enable count will be used.
+ *
+ * @disable_unused: Disable the clock atomically. Only called from
+ * clk_disable_unused for gate clocks with special needs.
+ * Called with enable_lock held. This function must not
+ * sleep.
+ *
+ * @recalc_rate Recalculate the rate of this clock, by querying hardware. The
* parent rate is an input parameter. It is up to the caller to
- * insure that the prepare_mutex is held across this call.
+ * ensure that the prepare_mutex is held across this call.
* Returns the calculated rate. Optional, but recommended - if
* this op is not set then clock rate will be initialized to 0.
*
@@ -89,7 +98,7 @@ struct clk_hw;
* implementations to split any work between atomic (enable) and sleepable
* (prepare) contexts. If enabling a clock requires code that might sleep,
* this must be done in clk_prepare. Clock enable code that will never be
- * called in a sleepable context may be implement in clk_enable.
+ * called in a sleepable context may be implemented in clk_enable.
*
* Typically, drivers will call clk_prepare when a clock may be needed later
* (eg. when a device is opened), and clk_enable when the clock is actually
@@ -102,6 +111,7 @@ struct clk_ops {
int (*enable)(struct clk_hw *hw);
void (*disable)(struct clk_hw *hw);
int (*is_enabled)(struct clk_hw *hw);
+ void (*disable_unused)(struct clk_hw *hw);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long,
@@ -327,19 +337,21 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
* error code; drivers must test for an error code after calling clk_register.
*/
struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
void clk_unregister(struct clk *clk);
+void devm_clk_unregister(struct device *dev, struct clk *clk);
/* helper functions */
const char *__clk_get_name(struct clk *clk);
struct clk_hw *__clk_get_hw(struct clk *clk);
u8 __clk_get_num_parents(struct clk *clk);
struct clk *__clk_get_parent(struct clk *clk);
-int __clk_get_enable_count(struct clk *clk);
-int __clk_get_prepare_count(struct clk *clk);
+unsigned int __clk_get_enable_count(struct clk *clk);
+unsigned int __clk_get_prepare_count(struct clk *clk);
unsigned long __clk_get_rate(struct clk *clk);
unsigned long __clk_get_flags(struct clk *clk);
-int __clk_is_enabled(struct clk *clk);
+bool __clk_is_enabled(struct clk *clk);
struct clk *__clk_lookup(const char *name);
/*
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index b60f6ba01d0c..a55b88eaf96a 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -11,6 +11,7 @@
#ifndef _LINUX_CPUFREQ_H
#define _LINUX_CPUFREQ_H
+#include <asm/cputime.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/threads.h>
@@ -22,6 +23,8 @@
#include <asm/div64.h>
#define CPUFREQ_NAME_LEN 16
+/* Print length for names. Extra 1 space for accomodating '\n' in prints */
+#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1)
/*********************************************************************
@@ -404,6 +407,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
void cpufreq_frequency_table_put_attr(unsigned int cpu);
-
-
#endif /* _LINUX_CPUFREQ_H */
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 279b1eaa8b73..3711b34dc4f9 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -82,13 +82,6 @@ cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
st_usage->driver_data = data;
}
-struct cpuidle_state_kobj {
- struct cpuidle_state *state;
- struct cpuidle_state_usage *state_usage;
- struct completion kobj_unregister;
- struct kobject kobj;
-};
-
struct cpuidle_device {
unsigned int registered:1;
unsigned int enabled:1;
@@ -98,7 +91,7 @@ struct cpuidle_device {
int state_count;
struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-
+ struct cpuidle_driver_kobj *kobj_driver;
struct list_head device_list;
struct kobject kobj;
struct completion kobj_unregister;
@@ -131,6 +124,7 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
struct cpuidle_driver {
const char *name;
struct module *owner;
+ int refcnt;
unsigned int power_specified:1;
/* set to 1 to use the core cpuidle time keeping (for all states). */
@@ -163,6 +157,10 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index));
extern int cpuidle_play_dead(void);
+extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
+extern int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu);
+extern void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu);
+
#else
static inline void disable_cpuidle(void) { }
static inline int cpuidle_idle_call(void) { return -ENODEV; }
@@ -189,7 +187,6 @@ static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index))
{ return -ENODEV; }
static inline int cpuidle_play_dead(void) {return -ENODEV; }
-
#endif
#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 281c72a3b9d5..e83ef39b3bea 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -25,12 +25,12 @@ struct devfreq;
* struct devfreq_dev_status - Data given from devfreq user device to
* governors. Represents the performance
* statistics.
- * @total_time The total time represented by this instance of
+ * @total_time: The total time represented by this instance of
* devfreq_dev_status
- * @busy_time The time that the device was working among the
+ * @busy_time: The time that the device was working among the
* total_time.
- * @current_frequency The operating frequency.
- * @private_data An entry not specified by the devfreq framework.
+ * @current_frequency: The operating frequency.
+ * @private_data: An entry not specified by the devfreq framework.
* A device and a specific governor may have their
* own protocol with private_data. However, because
* this is governor-specific, a governor using this
@@ -54,23 +54,27 @@ struct devfreq_dev_status {
/**
* struct devfreq_dev_profile - Devfreq's user device profile
- * @initial_freq The operating frequency when devfreq_add_device() is
+ * @initial_freq: The operating frequency when devfreq_add_device() is
* called.
- * @polling_ms The polling interval in ms. 0 disables polling.
- * @target The device should set its operating frequency at
+ * @polling_ms: The polling interval in ms. 0 disables polling.
+ * @target: The device should set its operating frequency at
* freq or lowest-upper-than-freq value. If freq is
* higher than any operable frequency, set maximum.
* Before returning, target function should set
* freq at the current frequency.
* The "flags" parameter's possible values are
* explained above with "DEVFREQ_FLAG_*" macros.
- * @get_dev_status The device should provide the current performance
+ * @get_dev_status: The device should provide the current performance
* status to devfreq, which is used by governors.
- * @exit An optional callback that is called when devfreq
+ * @get_cur_freq: The device should provide the current frequency
+ * at which it is operating.
+ * @exit: An optional callback that is called when devfreq
* is removing the devfreq object due to error or
* from devfreq_remove_device() call. If the user
* has registered devfreq->nb at a notifier-head,
* this is the time to unregister it.
+ * @freq_table: Optional list of frequencies to support statistics.
+ * @max_state: The size of freq_table.
*/
struct devfreq_dev_profile {
unsigned long initial_freq;
@@ -79,63 +83,63 @@ struct devfreq_dev_profile {
int (*target)(struct device *dev, unsigned long *freq, u32 flags);
int (*get_dev_status)(struct device *dev,
struct devfreq_dev_status *stat);
+ int (*get_cur_freq)(struct device *dev, unsigned long *freq);
void (*exit)(struct device *dev);
+
+ unsigned int *freq_table;
+ unsigned int max_state;
};
/**
* struct devfreq_governor - Devfreq policy governor
- * @name Governor's name
- * @get_target_freq Returns desired operating frequency for the device.
+ * @node: list node - contains registered devfreq governors
+ * @name: Governor's name
+ * @get_target_freq: Returns desired operating frequency for the device.
* Basically, get_target_freq will run
* devfreq_dev_profile.get_dev_status() to get the
* status of the device (load = busy_time / total_time).
* If no_central_polling is set, this callback is called
* only with update_devfreq() notified by OPP.
- * @init Called when the devfreq is being attached to a device
- * @exit Called when the devfreq is being removed from a
- * device. Governor should stop any internal routines
- * before return because related data may be
- * freed after exit().
- * @no_central_polling Do not use devfreq's central polling mechanism.
- * When this is set, devfreq will not call
- * get_target_freq with devfreq_monitor(). However,
- * devfreq will call get_target_freq with
- * devfreq_update() notified by OPP framework.
+ * @event_handler: Callback for devfreq core framework to notify events
+ * to governors. Events include per device governor
+ * init and exit, opp changes out of devfreq, suspend
+ * and resume of per device devfreq during device idle.
*
* Note that the callbacks are called with devfreq->lock locked by devfreq.
*/
struct devfreq_governor {
+ struct list_head node;
+
const char name[DEVFREQ_NAME_LEN];
int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
- int (*init)(struct devfreq *this);
- void (*exit)(struct devfreq *this);
- const bool no_central_polling;
+ int (*event_handler)(struct devfreq *devfreq,
+ unsigned int event, void *data);
};
/**
* struct devfreq - Device devfreq structure
- * @node list node - contains the devices with devfreq that have been
+ * @node: list node - contains the devices with devfreq that have been
* registered.
- * @lock a mutex to protect accessing devfreq.
- * @dev device registered by devfreq class. dev.parent is the device
+ * @lock: a mutex to protect accessing devfreq.
+ * @dev: device registered by devfreq class. dev.parent is the device
* using devfreq.
- * @profile device-specific devfreq profile
- * @governor method how to choose frequency based on the usage.
- * @nb notifier block used to notify devfreq object that it should
+ * @profile: device-specific devfreq profile
+ * @governor: method how to choose frequency based on the usage.
+ * @governor_name: devfreq governor name for use with this devfreq
+ * @nb: notifier block used to notify devfreq object that it should
* reevaluate operable frequencies. Devfreq users may use
* devfreq.nb to the corresponding register notifier call chain.
- * @polling_jiffies interval in jiffies.
- * @previous_freq previously configured frequency value.
- * @next_polling the number of remaining jiffies to poll with
- * "devfreq_monitor" executions to reevaluate
- * frequency/voltage of the device. Set by
- * profile's polling_ms interval.
- * @data Private data of the governor. The devfreq framework does not
+ * @work: delayed work for load monitoring.
+ * @previous_freq: previously configured frequency value.
+ * @data: Private data of the governor. The devfreq framework does not
* touch this.
- * @being_removed a flag to mark that this object is being removed in
- * order to prevent trying to remove the object multiple times.
- * @min_freq Limit minimum frequency requested by user (0: none)
- * @max_freq Limit maximum frequency requested by user (0: none)
+ * @min_freq: Limit minimum frequency requested by user (0: none)
+ * @max_freq: Limit maximum frequency requested by user (0: none)
+ * @stop_polling: devfreq polling status of a device.
+ * @total_trans: Number of devfreq transitions
+ * @trans_table: Statistics of devfreq transitions
+ * @time_in_state: Statistics of devfreq states
+ * @last_stat_updated: The last time stat updated
*
* This structure stores the devfreq information for a give device.
*
@@ -152,26 +156,33 @@ struct devfreq {
struct device dev;
struct devfreq_dev_profile *profile;
const struct devfreq_governor *governor;
+ char governor_name[DEVFREQ_NAME_LEN];
struct notifier_block nb;
+ struct delayed_work work;
- unsigned long polling_jiffies;
unsigned long previous_freq;
- unsigned int next_polling;
void *data; /* private data for governors */
- bool being_removed;
-
unsigned long min_freq;
unsigned long max_freq;
+ bool stop_polling;
+
+ /* information for device freqeuncy transition */
+ unsigned int total_trans;
+ unsigned int *trans_table;
+ unsigned long *time_in_state;
+ unsigned long last_stat_updated;
};
#if defined(CONFIG_PM_DEVFREQ)
extern struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- const struct devfreq_governor *governor,
+ const char *governor_name,
void *data);
extern int devfreq_remove_device(struct devfreq *devfreq);
+extern int devfreq_suspend_device(struct devfreq *devfreq);
+extern int devfreq_resume_device(struct devfreq *devfreq);
/* Helper functions for devfreq user device driver with OPP. */
extern struct opp *devfreq_recommended_opp(struct device *dev,
@@ -181,23 +192,13 @@ extern int devfreq_register_opp_notifier(struct device *dev,
extern int devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq);
-#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
-extern const struct devfreq_governor devfreq_powersave;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
-extern const struct devfreq_governor devfreq_performance;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
-extern const struct devfreq_governor devfreq_userspace;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
-extern const struct devfreq_governor devfreq_simple_ondemand;
+#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
/**
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
* and devfreq_add_device
- * @ upthreshold If the load is over this value, the frequency jumps.
+ * @upthreshold: If the load is over this value, the frequency jumps.
* Specify 0 to use the default. Valid value = 0 to 100.
- * @ downdifferential If the load is under upthreshold - downdifferential,
+ * @downdifferential: If the load is under upthreshold - downdifferential,
* the governor may consider slowing the frequency down.
* Specify 0 to use the default. Valid value = 0 to 100.
* downdifferential < upthreshold must hold.
@@ -214,7 +215,7 @@ struct devfreq_simple_ondemand_data {
#else /* !CONFIG_PM_DEVFREQ */
static struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- struct devfreq_governor *governor,
+ const char *governor_name,
void *data)
{
return NULL;
@@ -225,6 +226,16 @@ static int devfreq_remove_device(struct devfreq *devfreq)
return 0;
}
+static int devfreq_suspend_device(struct devfreq *devfreq)
+{
+ return 0;
+}
+
+static int devfreq_resume_device(struct devfreq *devfreq)
+{
+ return 0;
+}
+
static struct opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags)
{
@@ -243,11 +254,6 @@ static int devfreq_unregister_opp_notifier(struct device *dev,
return -EINVAL;
}
-#define devfreq_powersave NULL
-#define devfreq_performance NULL
-#define devfreq_userspace NULL
-#define devfreq_simple_ondemand NULL
-
#endif /* CONFIG_PM_DEVFREQ */
#endif /* __LINUX_DEVFREQ_H__ */
diff --git a/include/linux/device.h b/include/linux/device.h
index 86ef6ab553b1..05292e488346 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -190,6 +190,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
* @mod_name: Used for built-in modules.
* @suppress_bind_attrs: Disables bind/unbind via sysfs.
* @of_match_table: The open firmware table.
+ * @acpi_match_table: The ACPI match table.
* @probe: Called to query the existence of a specific device,
* whether this driver can work with it, and bind the driver
* to a specific device.
@@ -223,6 +224,7 @@ struct device_driver {
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
const struct of_device_id *of_match_table;
+ const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
@@ -576,6 +578,12 @@ struct device_dma_parameters {
unsigned long segment_boundary_mask;
};
+struct acpi_dev_node {
+#ifdef CONFIG_ACPI
+ void *handle;
+#endif
+};
+
/**
* struct device - The basic device structure
* @parent: The device's "parent" device, the device to which it is attached.
@@ -616,6 +624,7 @@ struct device_dma_parameters {
* @dma_mem: Internal for coherent mem override.
* @archdata: For arch-specific additions.
* @of_node: Associated device tree node.
+ * @acpi_node: Associated ACPI device node.
* @devt: For creating the sysfs "dev".
* @id: device instance
* @devres_lock: Spinlock to protect the resource of the device.
@@ -680,6 +689,7 @@ struct device {
struct dev_archdata archdata;
struct device_node *of_node; /* associated device tree node */
+ struct acpi_dev_node acpi_node; /* associated ACPI device node */
dev_t devt; /* dev_t, creates the sysfs "dev" */
u32 id; /* device instance */
@@ -700,6 +710,14 @@ static inline struct device *kobj_to_dev(struct kobject *kobj)
return container_of(kobj, struct device, kobj);
}
+#ifdef CONFIG_ACPI
+#define ACPI_HANDLE(dev) ((dev)->acpi_node.handle)
+#define ACPI_HANDLE_SET(dev, _handle_) (dev)->acpi_node.handle = (_handle_)
+#else
+#define ACPI_HANDLE(dev) (NULL)
+#define ACPI_HANDLE_SET(dev, _handle_) do { } while (0)
+#endif
+
/* Get the wakeup routines, which depend on struct device */
#include <linux/pm_wakeup.h>
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index 2f303e4b7ed3..01b5c84be828 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -68,7 +68,7 @@ struct device;
extern struct cma *dma_contiguous_default_area;
void dma_contiguous_reserve(phys_addr_t addr_limit);
-int dma_declare_contiguous(struct device *dev, unsigned long size,
+int dma_declare_contiguous(struct device *dev, phys_addr_t size,
phys_addr_t base, phys_addr_t limit);
struct page *dma_alloc_from_contiguous(struct device *dev, int count,
@@ -83,7 +83,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
static inline void dma_contiguous_reserve(phys_addr_t limit) { }
static inline
-int dma_declare_contiguous(struct device *dev, unsigned long size,
+int dma_declare_contiguous(struct device *dev, phys_addr_t size,
phys_addr_t base, phys_addr_t limit)
{
return -ENOSYS;
diff --git a/include/linux/edac.h b/include/linux/edac.h
index bab9f8473dc1..1b8c02b36f76 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -533,6 +533,7 @@ struct csrow_info {
u32 ue_count; /* Uncorrectable Errors for this csrow */
u32 ce_count; /* Correctable Errors for this csrow */
+ u32 nr_pages; /* combined pages count of all channels */
struct mem_ctl_info *mci; /* the parent */
@@ -667,6 +668,8 @@ struct mem_ctl_info {
u32 fake_inject_ue;
u16 fake_inject_count;
#endif
+ __u8 csbased : 1, /* csrow-based memory controller */
+ __resv : 7;
};
#endif
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index d09af4b67cf1..b90091af5798 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -177,6 +177,7 @@ static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {}
static inline void thaw_kernel_threads(void) {}
+static inline bool try_to_freeze_nowarn(void) { return false; }
static inline bool try_to_freeze(void) { return false; }
static inline void freezer_do_not_count(void) {}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b33cfc97b9ca..75fe9a134803 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -462,8 +462,6 @@ struct block_device {
int bd_fsfreeze_count;
/* Mutex for freeze */
struct mutex bd_fsfreeze_mutex;
- /* A semaphore that prevents I/O while block size is being changed */
- struct percpu_rw_semaphore bd_block_size_semaphore;
};
/*
@@ -2049,7 +2047,6 @@ 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 *);
@@ -2379,8 +2376,6 @@ extern int generic_segment_checks(const struct iovec *iov,
unsigned long *nr_segs, size_t *count, int access_flags);
/* fs/block_dev.c */
-extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos);
extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 02c1c9710be0..d0a79678f169 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -31,6 +31,7 @@ struct vm_area_struct;
#define ___GFP_THISNODE 0x40000u
#define ___GFP_RECLAIMABLE 0x80000u
#define ___GFP_NOTRACK 0x200000u
+#define ___GFP_NO_KSWAPD 0x400000u
#define ___GFP_OTHER_NODE 0x800000u
#define ___GFP_WRITE 0x1000000u
@@ -85,6 +86,7 @@ struct vm_area_struct;
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
#define __GFP_NOTRACK ((__force gfp_t)___GFP_NOTRACK) /* Don't track with kmemcheck */
+#define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD)
#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
#define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */
@@ -114,7 +116,8 @@ struct vm_area_struct;
__GFP_MOVABLE)
#define GFP_IOFS (__GFP_IO | __GFP_FS)
#define GFP_TRANSHUGE (GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
- __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN)
+ __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
+ __GFP_NO_KSWAPD)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b3a190..bfe665621536 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq)
return -EINVAL;
}
-#endif
+#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
-#else
+#else /* ! CONFIG_GENERIC_GPIO */
#include <linux/kernel.h>
#include <linux/types.h>
@@ -231,6 +231,21 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL;
}
-#endif
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+ unsigned int gpio_offset, unsigned int pin_offset,
+ unsigned int npins)
+{
+ WARN_ON(1);
+ return -EINVAL;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+ WARN_ON(1);
+}
+
+#endif /* ! CONFIG_GENERIC_GPIO */
#endif /* __LINUX_GPIO_H */
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index 6ae9c631a1be..0464c85e63fd 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -1,35 +1,8 @@
#ifndef _LINUX_HW_BREAKPOINT_H
#define _LINUX_HW_BREAKPOINT_H
-enum {
- HW_BREAKPOINT_LEN_1 = 1,
- HW_BREAKPOINT_LEN_2 = 2,
- HW_BREAKPOINT_LEN_4 = 4,
- HW_BREAKPOINT_LEN_8 = 8,
-};
-
-enum {
- HW_BREAKPOINT_EMPTY = 0,
- HW_BREAKPOINT_R = 1,
- HW_BREAKPOINT_W = 2,
- HW_BREAKPOINT_RW = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
- HW_BREAKPOINT_X = 4,
- HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
-};
-
-enum bp_type_idx {
- TYPE_INST = 0,
-#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
- TYPE_DATA = 0,
-#else
- TYPE_DATA = 1,
-#endif
- TYPE_MAX
-};
-
-#ifdef __KERNEL__
-
#include <linux/perf_event.h>
+#include <uapi/linux/hw_breakpoint.h>
#ifdef CONFIG_HAVE_HW_BREAKPOINT
@@ -151,6 +124,4 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
}
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
-#endif /* __KERNEL__ */
-
#endif /* _LINUX_HW_BREAKPOINT_H */
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
index df804ba73e0b..92a0dc75bc74 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/i2c-omap.h
@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
u32 clkrate;
u32 rev;
u32 flags;
+ void (*set_mpu_wkup_lat)(struct device *dev, long set);
};
#endif
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 800de224336b..d0c4db7b4872 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -259,6 +259,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
* @platform_data: stored in i2c_client.dev.platform_data
* @archdata: copied into i2c_client.dev.archdata
* @of_node: pointer to OpenFirmware device node
+ * @acpi_node: ACPI device node
* @irq: stored in i2c_client.irq
*
* I2C doesn't actually support hardware probing, although controllers and
@@ -279,6 +280,7 @@ struct i2c_board_info {
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;
+ struct acpi_dev_node acpi_node;
int irq;
};
@@ -501,4 +503,11 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
i2c_del_driver)
#endif /* I2C */
+
+#if IS_ENABLED(CONFIG_ACPI_I2C)
+extern void acpi_i2c_register_devices(struct i2c_adapter *adap);
+#else
+static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
+#endif
+
#endif /* _LINUX_I2C_H */
diff --git a/include/linux/i2c/pcf857x.h b/include/linux/i2c/pcf857x.h
index 781e6bd06c34..0767a2a6b2f1 100644
--- a/include/linux/i2c/pcf857x.h
+++ b/include/linux/i2c/pcf857x.h
@@ -10,7 +10,6 @@
* @setup: optional callback issued once the GPIOs are valid
* @teardown: optional callback issued before the GPIOs are invalidated
* @context: optional parameter passed to setup() and teardown()
- * @irq: optional interrupt number
*
* In addition to the I2C_BOARD_INFO() state appropriate to each chip,
* the i2c_board_info used with the pcf875x driver must provide its
@@ -40,8 +39,6 @@ struct pcf857x_platform_data {
int gpio, unsigned ngpio,
void *context);
void *context;
-
- int irq;
};
#endif /* __LINUX_PCF857X_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index e59041e21df3..f63692d6902e 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -93,13 +93,13 @@
#define __exit __section(.exit.text) __exitused __cold notrace
-/* Used for HOTPLUG */
-#define __devinit __section(.devinit.text) __cold notrace
-#define __devinitdata __section(.devinit.data)
-#define __devinitconst __constsection(.devinit.rodata)
-#define __devexit __section(.devexit.text) __exitused __cold notrace
-#define __devexitdata __section(.devexit.data)
-#define __devexitconst __constsection(.devexit.rodata)
+/* Used for HOTPLUG, but that is always enabled now, so just make them noops */
+#define __devinit
+#define __devinitdata
+#define __devinitconst
+#define __devexit
+#define __devexitdata
+#define __devexitconst
/* Used for HOTPLUG_CPU */
#define __cpuinit __section(.cpuinit.text) __cold notrace
@@ -126,10 +126,6 @@
#define __INITRODATA .section ".init.rodata","a",%progbits
#define __FINITDATA .previous
-#define __DEVINIT .section ".devinit.text", "ax"
-#define __DEVINITDATA .section ".devinit.data", "aw"
-#define __DEVINITRODATA .section ".devinit.rodata", "a"
-
#define __CPUINIT .section ".cpuinit.text", "ax"
#define __CPUINITDATA .section ".cpuinit.data", "aw"
#define __CPUINITRODATA .section ".cpuinit.rodata", "a"
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a123b13b70fd..7d8dfc7392f1 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -701,6 +701,13 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
#define COMPACTION_BUILD 0
#endif
+/* This helps us to avoid #ifdef CONFIG_SYMBOL_PREFIX */
+#ifdef CONFIG_SYMBOL_PREFIX
+#define SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#else
+#define SYMBOL_PREFIX ""
+#endif
+
/* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
# define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 1e57449395b1..939b11268c86 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -203,7 +203,6 @@ extern struct kobject *power_kobj;
/* The global /sys/firmware/ kobject for people to chain off of */
extern struct kobject *firmware_kobj;
-#if defined(CONFIG_HOTPLUG)
int kobject_uevent(struct kobject *kobj, enum kobject_action action);
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp[]);
@@ -213,22 +212,5 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
int kobject_action_type(const char *buf, size_t count,
enum kobject_action *type);
-#else
-static inline int kobject_uevent(struct kobject *kobj,
- enum kobject_action action)
-{ return 0; }
-static inline int kobject_uevent_env(struct kobject *kobj,
- enum kobject_action action,
- char *envp[])
-{ return 0; }
-
-static inline __printf(2, 3)
-int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
-{ return -ENOMEM; }
-
-static inline int kobject_action_type(const char *buf, size_t count,
- enum kobject_action *type)
-{ return -EINVAL; }
-#endif
#endif /* _KOBJECT_H_ */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index e5ccb9ddd90e..dbd212723b74 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -82,16 +82,6 @@ static inline void mpol_cond_put(struct mempolicy *pol)
__mpol_put(pol);
}
-extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
- struct mempolicy *frompol);
-static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol,
- struct mempolicy *frompol)
-{
- if (!frompol)
- return frompol;
- return __mpol_cond_copy(tompol, frompol);
-}
-
extern struct mempolicy *__mpol_dup(struct mempolicy *pol);
static inline struct mempolicy *mpol_dup(struct mempolicy *pol)
{
@@ -215,12 +205,6 @@ static inline void mpol_cond_put(struct mempolicy *pol)
{
}
-static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to,
- struct mempolicy *from)
-{
- return from;
-}
-
static inline void mpol_get(struct mempolicy *pol)
{
}
diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h
index a0ca0dca1244..478672ed0c3d 100644
--- a/include/linux/mfd/88pm80x.h
+++ b/include/linux/mfd/88pm80x.h
@@ -364,6 +364,6 @@ static inline int pm80x_dev_resume(struct device *dev)
#endif
extern int pm80x_init(struct i2c_client *client,
- const struct i2c_device_id *id) __devinit;
+ const struct i2c_device_id *id);
extern int pm80x_deinit(struct i2c_client *client);
#endif /* __LINUX_MFD_88PM80X_H */
diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h
index 1491044efa10..1cb5698b4d76 100644
--- a/include/linux/mfd/abx500/ab8500.h
+++ b/include/linux/mfd/abx500/ab8500.h
@@ -291,9 +291,9 @@ struct ab8500_platform_data {
struct ab8500_codec_platform_data *codec;
};
-extern int __devinit ab8500_init(struct ab8500 *ab8500,
+extern int ab8500_init(struct ab8500 *ab8500,
enum ab8500_version version);
-extern int __devexit ab8500_exit(struct ab8500 *ab8500);
+extern int ab8500_exit(struct ab8500 *ab8500);
extern int ab8500_suspend(struct ab8500 *ab8500);
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index b82f6ee66a0b..6ee4247df11e 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -515,7 +515,6 @@ enum romcode_read prcmu_get_rc_p2a(void);
enum ap_pwrst prcmu_get_xp70_current_state(void);
bool prcmu_has_arm_maxopp(void);
struct prcmu_fw_version *prcmu_get_fw_version(void);
-int prcmu_request_ape_opp_100_voltage(bool enable);
int prcmu_release_usb_wakeup_state(void);
void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
struct prcmu_auto_pm_config *idle);
@@ -564,6 +563,7 @@ int db8500_prcmu_set_arm_opp(u8 opp);
int db8500_prcmu_get_arm_opp(void);
int db8500_prcmu_set_ape_opp(u8 opp);
int db8500_prcmu_get_ape_opp(void);
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable);
int db8500_prcmu_set_ddr_opp(u8 opp);
int db8500_prcmu_get_ddr_opp(void);
@@ -610,7 +610,7 @@ static inline int db8500_prcmu_get_ape_opp(void)
return APE_100_OPP;
}
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+static inline int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
{
return 0;
}
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index c410d99bd667..c202d6c4d879 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -336,6 +336,11 @@ static inline int prcmu_get_ape_opp(void)
return db8500_prcmu_get_ape_opp();
}
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+ return db8500_prcmu_request_ape_opp_100_voltage(enable);
+}
+
static inline void prcmu_system_reset(u16 reset_code)
{
return db8500_prcmu_system_reset(reset_code);
@@ -507,6 +512,11 @@ static inline int prcmu_get_ape_opp(void)
return APE_100_OPP;
}
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+ return 0;
+}
+
static inline int prcmu_set_arm_opp(u8 opp)
{
return 0;
diff --git a/include/linux/mfd/pm8xxx/irq.h b/include/linux/mfd/pm8xxx/irq.h
index 4b21769f4483..f83d6b43ecbb 100644
--- a/include/linux/mfd/pm8xxx/irq.h
+++ b/include/linux/mfd/pm8xxx/irq.h
@@ -37,21 +37,21 @@ struct pm_irq_chip;
#ifdef CONFIG_MFD_PM8XXX_IRQ
int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq);
-struct pm_irq_chip * __devinit pm8xxx_irq_init(struct device *dev,
+struct pm_irq_chip *pm8xxx_irq_init(struct device *dev,
const struct pm8xxx_irq_platform_data *pdata);
-int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip);
+int pm8xxx_irq_exit(struct pm_irq_chip *chip);
#else
static inline int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
{
return -ENXIO;
}
-static inline struct pm_irq_chip * __devinit pm8xxx_irq_init(
+static inline struct pm_irq_chip *pm8xxx_irq_init(
const struct device *dev,
const struct pm8xxx_irq_platform_data *pdata)
{
return ERR_PTR(-ENXIO);
}
-static inline int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
+static inline int pm8xxx_irq_exit(struct pm_irq_chip *chip)
{
return -ENXIO;
}
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
new file mode 100644
index 000000000000..a8d393e3066b
--- /dev/null
+++ b/include/linux/mfd/rtsx_common.h
@@ -0,0 +1,48 @@
+/* Driver for Realtek driver-based card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_COMMON_H
+#define __RTSX_COMMON_H
+
+#define DRV_NAME_RTSX_PCI "rtsx_pci"
+#define DRV_NAME_RTSX_PCI_SDMMC "rtsx_pci_sdmmc"
+#define DRV_NAME_RTSX_PCI_MS "rtsx_pci_ms"
+
+#define RTSX_REG_PAIR(addr, val) (((u32)(addr) << 16) | (u8)(val))
+
+#define RTSX_SSC_DEPTH_4M 0x01
+#define RTSX_SSC_DEPTH_2M 0x02
+#define RTSX_SSC_DEPTH_1M 0x03
+#define RTSX_SSC_DEPTH_500K 0x04
+#define RTSX_SSC_DEPTH_250K 0x05
+
+#define RTSX_SD_CARD 0
+#define RTSX_MS_CARD 1
+
+struct platform_device;
+
+struct rtsx_slot {
+ struct platform_device *p_dev;
+ void (*card_event)(struct platform_device *p_dev);
+};
+
+#endif
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
new file mode 100644
index 000000000000..060b721fcbfb
--- /dev/null
+++ b/include/linux/mfd/rtsx_pci.h
@@ -0,0 +1,794 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * 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:
+ * Wei WANG <wei_wang@realsil.com.cn>
+ * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_PCI_H
+#define __RTSX_PCI_H
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+
+#include "rtsx_common.h"
+
+#define MAX_RW_REG_CNT 1024
+
+/* PCI Operation Register Address */
+#define RTSX_HCBAR 0x00
+#define RTSX_HCBCTLR 0x04
+#define RTSX_HDBAR 0x08
+#define RTSX_HDBCTLR 0x0C
+#define RTSX_HAIMR 0x10
+#define RTSX_BIPR 0x14
+#define RTSX_BIER 0x18
+
+/* Host command buffer control register */
+#define STOP_CMD (0x01 << 28)
+
+/* Host data buffer control register */
+#define SDMA_MODE 0x00
+#define ADMA_MODE (0x02 << 26)
+#define STOP_DMA (0x01 << 28)
+#define TRIG_DMA (0x01 << 31)
+
+/* Host access internal memory register */
+#define HAIMR_TRANS_START (0x01 << 31)
+#define HAIMR_READ 0x00
+#define HAIMR_WRITE (0x01 << 30)
+#define HAIMR_READ_START (HAIMR_TRANS_START | HAIMR_READ)
+#define HAIMR_WRITE_START (HAIMR_TRANS_START | HAIMR_WRITE)
+#define HAIMR_TRANS_END (HAIMR_TRANS_START)
+
+/* Bus interrupt pending register */
+#define CMD_DONE_INT (1 << 31)
+#define DATA_DONE_INT (1 << 30)
+#define TRANS_OK_INT (1 << 29)
+#define TRANS_FAIL_INT (1 << 28)
+#define XD_INT (1 << 27)
+#define MS_INT (1 << 26)
+#define SD_INT (1 << 25)
+#define GPIO0_INT (1 << 24)
+#define OC_INT (1 << 23)
+#define SD_WRITE_PROTECT (1 << 19)
+#define XD_EXIST (1 << 18)
+#define MS_EXIST (1 << 17)
+#define SD_EXIST (1 << 16)
+#define DELINK_INT GPIO0_INT
+#define MS_OC_INT (1 << 23)
+#define SD_OC_INT (1 << 22)
+
+#define CARD_INT (XD_INT | MS_INT | SD_INT)
+#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
+#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | \
+ CARD_INT | GPIO0_INT | OC_INT)
+
+#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST)
+
+/* Bus interrupt enable register */
+#define CMD_DONE_INT_EN (1 << 31)
+#define DATA_DONE_INT_EN (1 << 30)
+#define TRANS_OK_INT_EN (1 << 29)
+#define TRANS_FAIL_INT_EN (1 << 28)
+#define XD_INT_EN (1 << 27)
+#define MS_INT_EN (1 << 26)
+#define SD_INT_EN (1 << 25)
+#define GPIO0_INT_EN (1 << 24)
+#define OC_INT_EN (1 << 23)
+#define DELINK_INT_EN GPIO0_INT_EN
+#define MS_OC_INT_EN (1 << 23)
+#define SD_OC_INT_EN (1 << 22)
+
+#define READ_REG_CMD 0
+#define WRITE_REG_CMD 1
+#define CHECK_REG_CMD 2
+
+/*
+ * macros for easy use
+ */
+#define rtsx_pci_writel(pcr, reg, value) \
+ iowrite32(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readl(pcr, reg) \
+ ioread32((pcr)->remap_addr + reg)
+#define rtsx_pci_writew(pcr, reg, value) \
+ iowrite16(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readw(pcr, reg) \
+ ioread16((pcr)->remap_addr + reg)
+#define rtsx_pci_writeb(pcr, reg, value) \
+ iowrite8(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readb(pcr, reg) \
+ ioread8((pcr)->remap_addr + reg)
+
+#define rtsx_pci_read_config_byte(pcr, where, val) \
+ pci_read_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_byte(pcr, where, val) \
+ pci_write_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_read_config_dword(pcr, where, val) \
+ pci_read_config_dword((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_dword(pcr, where, val) \
+ pci_write_config_dword((pcr)->pci, where, val)
+
+#define STATE_TRANS_NONE 0
+#define STATE_TRANS_CMD 1
+#define STATE_TRANS_BUF 2
+#define STATE_TRANS_SG 3
+
+#define TRANS_NOT_READY 0
+#define TRANS_RESULT_OK 1
+#define TRANS_RESULT_FAIL 2
+#define TRANS_NO_DEVICE 3
+
+#define RTSX_RESV_BUF_LEN 4096
+#define HOST_CMDS_BUF_LEN 1024
+#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
+#define HOST_SG_TBL_ITEMS (HOST_SG_TBL_BUF_LEN / 8)
+#define MAX_SG_ITEM_LEN 0x80000
+
+#define HOST_TO_DEVICE 0
+#define DEVICE_TO_HOST 1
+
+#define MAX_PHASE 31
+#define RX_TUNING_CNT 3
+
+/* SG descriptor */
+#define SG_INT 0x04
+#define SG_END 0x02
+#define SG_VALID 0x01
+
+#define SG_NO_OP 0x00
+#define SG_TRANS_DATA (0x02 << 4)
+#define SG_LINK_DESC (0x03 << 4)
+
+/* SD bank voltage */
+#define SD_IO_3V3 0
+#define SD_IO_1V8 1
+
+
+/* Card Clock Enable Register */
+#define SD_CLK_EN 0x04
+#define MS_CLK_EN 0x08
+
+/* Card Select Register */
+#define SD_MOD_SEL 2
+#define MS_MOD_SEL 3
+
+/* Card Output Enable Register */
+#define SD_OUTPUT_EN 0x04
+#define MS_OUTPUT_EN 0x08
+
+/* CARD_SHARE_MODE */
+#define CARD_SHARE_MASK 0x0F
+#define CARD_SHARE_MULTI_LUN 0x00
+#define CARD_SHARE_NORMAL 0x00
+#define CARD_SHARE_48_SD 0x04
+#define CARD_SHARE_48_MS 0x08
+/* CARD_SHARE_MODE for barossa */
+#define CARD_SHARE_BAROSSA_SD 0x01
+#define CARD_SHARE_BAROSSA_MS 0x02
+
+/* SD30_DRIVE_SEL */
+#define DRIVER_TYPE_A 0x05
+#define DRIVER_TYPE_B 0x03
+#define DRIVER_TYPE_C 0x02
+#define DRIVER_TYPE_D 0x01
+
+/* FPDCTL */
+#define SSC_POWER_DOWN 0x01
+#define SD_OC_POWER_DOWN 0x02
+#define ALL_POWER_DOWN 0x07
+#define OC_POWER_DOWN 0x06
+
+/* CLK_CTL */
+#define CHANGE_CLK 0x01
+
+/* LDO_CTL */
+#define BPP_LDO_POWB 0x03
+#define BPP_LDO_ON 0x00
+#define BPP_LDO_SUSPEND 0x02
+#define BPP_LDO_OFF 0x03
+
+/* CD_PAD_CTL */
+#define CD_DISABLE_MASK 0x07
+#define MS_CD_DISABLE 0x04
+#define SD_CD_DISABLE 0x02
+#define XD_CD_DISABLE 0x01
+#define CD_DISABLE 0x07
+#define CD_ENABLE 0x00
+#define MS_CD_EN_ONLY 0x03
+#define SD_CD_EN_ONLY 0x05
+#define XD_CD_EN_ONLY 0x06
+#define FORCE_CD_LOW_MASK 0x38
+#define FORCE_CD_XD_LOW 0x08
+#define FORCE_CD_SD_LOW 0x10
+#define FORCE_CD_MS_LOW 0x20
+#define CD_AUTO_DISABLE 0x40
+
+/* SD_STAT1 */
+#define SD_CRC7_ERR 0x80
+#define SD_CRC16_ERR 0x40
+#define SD_CRC_WRITE_ERR 0x20
+#define SD_CRC_WRITE_ERR_MASK 0x1C
+#define GET_CRC_TIME_OUT 0x02
+#define SD_TUNING_COMPARE_ERR 0x01
+
+/* SD_STAT2 */
+#define SD_RSP_80CLK_TIMEOUT 0x01
+
+/* SD_BUS_STAT */
+#define SD_CLK_TOGGLE_EN 0x80
+#define SD_CLK_FORCE_STOP 0x40
+#define SD_DAT3_STATUS 0x10
+#define SD_DAT2_STATUS 0x08
+#define SD_DAT1_STATUS 0x04
+#define SD_DAT0_STATUS 0x02
+#define SD_CMD_STATUS 0x01
+
+/* SD_PAD_CTL */
+#define SD_IO_USING_1V8 0x80
+#define SD_IO_USING_3V3 0x7F
+#define TYPE_A_DRIVING 0x00
+#define TYPE_B_DRIVING 0x01
+#define TYPE_C_DRIVING 0x02
+#define TYPE_D_DRIVING 0x03
+
+/* SD_SAMPLE_POINT_CTL */
+#define DDR_FIX_RX_DAT 0x00
+#define DDR_VAR_RX_DAT 0x80
+#define DDR_FIX_RX_DAT_EDGE 0x00
+#define DDR_FIX_RX_DAT_14_DELAY 0x40
+#define DDR_FIX_RX_CMD 0x00
+#define DDR_VAR_RX_CMD 0x20
+#define DDR_FIX_RX_CMD_POS_EDGE 0x00
+#define DDR_FIX_RX_CMD_14_DELAY 0x10
+#define SD20_RX_POS_EDGE 0x00
+#define SD20_RX_14_DELAY 0x08
+#define SD20_RX_SEL_MASK 0x08
+
+/* SD_PUSH_POINT_CTL */
+#define DDR_FIX_TX_CMD_DAT 0x00
+#define DDR_VAR_TX_CMD_DAT 0x80
+#define DDR_FIX_TX_DAT_14_TSU 0x00
+#define DDR_FIX_TX_DAT_12_TSU 0x40
+#define DDR_FIX_TX_CMD_NEG_EDGE 0x00
+#define DDR_FIX_TX_CMD_14_AHEAD 0x20
+#define SD20_TX_NEG_EDGE 0x00
+#define SD20_TX_14_AHEAD 0x10
+#define SD20_TX_SEL_MASK 0x10
+#define DDR_VAR_SDCLK_POL_SWAP 0x01
+
+/* SD_TRANSFER */
+#define SD_TRANSFER_START 0x80
+#define SD_TRANSFER_END 0x40
+#define SD_STAT_IDLE 0x20
+#define SD_TRANSFER_ERR 0x10
+/* SD Transfer Mode definition */
+#define SD_TM_NORMAL_WRITE 0x00
+#define SD_TM_AUTO_WRITE_3 0x01
+#define SD_TM_AUTO_WRITE_4 0x02
+#define SD_TM_AUTO_READ_3 0x05
+#define SD_TM_AUTO_READ_4 0x06
+#define SD_TM_CMD_RSP 0x08
+#define SD_TM_AUTO_WRITE_1 0x09
+#define SD_TM_AUTO_WRITE_2 0x0A
+#define SD_TM_NORMAL_READ 0x0C
+#define SD_TM_AUTO_READ_1 0x0D
+#define SD_TM_AUTO_READ_2 0x0E
+#define SD_TM_AUTO_TUNING 0x0F
+
+/* SD_VPTX_CTL / SD_VPRX_CTL */
+#define PHASE_CHANGE 0x80
+#define PHASE_NOT_RESET 0x40
+
+/* SD_DCMPS_TX_CTL / SD_DCMPS_RX_CTL */
+#define DCMPS_CHANGE 0x80
+#define DCMPS_CHANGE_DONE 0x40
+#define DCMPS_ERROR 0x20
+#define DCMPS_CURRENT_PHASE 0x1F
+
+/* SD Configure 1 Register */
+#define SD_CLK_DIVIDE_0 0x00
+#define SD_CLK_DIVIDE_256 0xC0
+#define SD_CLK_DIVIDE_128 0x80
+#define SD_BUS_WIDTH_1BIT 0x00
+#define SD_BUS_WIDTH_4BIT 0x01
+#define SD_BUS_WIDTH_8BIT 0x02
+#define SD_ASYNC_FIFO_NOT_RST 0x10
+#define SD_20_MODE 0x00
+#define SD_DDR_MODE 0x04
+#define SD_30_MODE 0x08
+
+#define SD_CLK_DIVIDE_MASK 0xC0
+
+/* SD_CMD_STATE */
+#define SD_CMD_IDLE 0x80
+
+/* SD_DATA_STATE */
+#define SD_DATA_IDLE 0x80
+
+/* DCM_DRP_CTL */
+#define DCM_RESET 0x08
+#define DCM_LOCKED 0x04
+#define DCM_208M 0x00
+#define DCM_TX 0x01
+#define DCM_RX 0x02
+
+/* DCM_DRP_TRIG */
+#define DRP_START 0x80
+#define DRP_DONE 0x40
+
+/* DCM_DRP_CFG */
+#define DRP_WRITE 0x80
+#define DRP_READ 0x00
+#define DCM_WRITE_ADDRESS_50 0x50
+#define DCM_WRITE_ADDRESS_51 0x51
+#define DCM_READ_ADDRESS_00 0x00
+#define DCM_READ_ADDRESS_51 0x51
+
+/* IRQSTAT0 */
+#define DMA_DONE_INT 0x80
+#define SUSPEND_INT 0x40
+#define LINK_RDY_INT 0x20
+#define LINK_DOWN_INT 0x10
+
+/* DMACTL */
+#define DMA_RST 0x80
+#define DMA_BUSY 0x04
+#define DMA_DIR_TO_CARD 0x00
+#define DMA_DIR_FROM_CARD 0x02
+#define DMA_EN 0x01
+#define DMA_128 (0 << 4)
+#define DMA_256 (1 << 4)
+#define DMA_512 (2 << 4)
+#define DMA_1024 (3 << 4)
+#define DMA_PACK_SIZE_MASK 0x30
+
+/* SSC_CTL1 */
+#define SSC_RSTB 0x80
+#define SSC_8X_EN 0x40
+#define SSC_FIX_FRAC 0x20
+#define SSC_SEL_1M 0x00
+#define SSC_SEL_2M 0x08
+#define SSC_SEL_4M 0x10
+#define SSC_SEL_8M 0x18
+
+/* SSC_CTL2 */
+#define SSC_DEPTH_MASK 0x07
+#define SSC_DEPTH_DISALBE 0x00
+#define SSC_DEPTH_4M 0x01
+#define SSC_DEPTH_2M 0x02
+#define SSC_DEPTH_1M 0x03
+#define SSC_DEPTH_500K 0x04
+#define SSC_DEPTH_250K 0x05
+
+/* System Clock Control Register */
+#define CLK_LOW_FREQ 0x01
+
+/* System Clock Divider Register */
+#define CLK_DIV_1 0x01
+#define CLK_DIV_2 0x02
+#define CLK_DIV_4 0x03
+#define CLK_DIV_8 0x04
+
+/* MS_CFG */
+#define SAMPLE_TIME_RISING 0x00
+#define SAMPLE_TIME_FALLING 0x80
+#define PUSH_TIME_DEFAULT 0x00
+#define PUSH_TIME_ODD 0x40
+#define NO_EXTEND_TOGGLE 0x00
+#define EXTEND_TOGGLE_CHK 0x20
+#define MS_BUS_WIDTH_1 0x00
+#define MS_BUS_WIDTH_4 0x10
+#define MS_BUS_WIDTH_8 0x18
+#define MS_2K_SECTOR_MODE 0x04
+#define MS_512_SECTOR_MODE 0x00
+#define MS_TOGGLE_TIMEOUT_EN 0x00
+#define MS_TOGGLE_TIMEOUT_DISEN 0x01
+#define MS_NO_CHECK_INT 0x02
+
+/* MS_TRANS_CFG */
+#define WAIT_INT 0x80
+#define NO_WAIT_INT 0x00
+#define NO_AUTO_READ_INT_REG 0x00
+#define AUTO_READ_INT_REG 0x40
+#define MS_CRC16_ERR 0x20
+#define MS_RDY_TIMEOUT 0x10
+#define MS_INT_CMDNK 0x08
+#define MS_INT_BREQ 0x04
+#define MS_INT_ERR 0x02
+#define MS_INT_CED 0x01
+
+/* MS_TRANSFER */
+#define MS_TRANSFER_START 0x80
+#define MS_TRANSFER_END 0x40
+#define MS_TRANSFER_ERR 0x20
+#define MS_BS_STATE 0x10
+#define MS_TM_READ_BYTES 0x00
+#define MS_TM_NORMAL_READ 0x01
+#define MS_TM_WRITE_BYTES 0x04
+#define MS_TM_NORMAL_WRITE 0x05
+#define MS_TM_AUTO_READ 0x08
+#define MS_TM_AUTO_WRITE 0x0C
+
+/* SD Configure 2 Register */
+#define SD_CALCULATE_CRC7 0x00
+#define SD_NO_CALCULATE_CRC7 0x80
+#define SD_CHECK_CRC16 0x00
+#define SD_NO_CHECK_CRC16 0x40
+#define SD_NO_CHECK_WAIT_CRC_TO 0x20
+#define SD_WAIT_BUSY_END 0x08
+#define SD_NO_WAIT_BUSY_END 0x00
+#define SD_CHECK_CRC7 0x00
+#define SD_NO_CHECK_CRC7 0x04
+#define SD_RSP_LEN_0 0x00
+#define SD_RSP_LEN_6 0x01
+#define SD_RSP_LEN_17 0x02
+/* SD/MMC Response Type Definition */
+#define SD_RSP_TYPE_R0 0x04
+#define SD_RSP_TYPE_R1 0x01
+#define SD_RSP_TYPE_R1b 0x09
+#define SD_RSP_TYPE_R2 0x02
+#define SD_RSP_TYPE_R3 0x05
+#define SD_RSP_TYPE_R4 0x05
+#define SD_RSP_TYPE_R5 0x01
+#define SD_RSP_TYPE_R6 0x01
+#define SD_RSP_TYPE_R7 0x01
+
+/* SD_CONFIURE3 */
+#define SD_RSP_80CLK_TIMEOUT_EN 0x01
+
+/* Card Transfer Reset Register */
+#define SPI_STOP 0x01
+#define XD_STOP 0x02
+#define SD_STOP 0x04
+#define MS_STOP 0x08
+#define SPI_CLR_ERR 0x10
+#define XD_CLR_ERR 0x20
+#define SD_CLR_ERR 0x40
+#define MS_CLR_ERR 0x80
+
+/* Card Data Source Register */
+#define PINGPONG_BUFFER 0x01
+#define RING_BUFFER 0x00
+
+/* Card Power Control Register */
+#define PMOS_STRG_MASK 0x10
+#define PMOS_STRG_800mA 0x10
+#define PMOS_STRG_400mA 0x00
+#define SD_POWER_OFF 0x03
+#define SD_PARTIAL_POWER_ON 0x01
+#define SD_POWER_ON 0x00
+#define SD_POWER_MASK 0x03
+#define MS_POWER_OFF 0x0C
+#define MS_PARTIAL_POWER_ON 0x04
+#define MS_POWER_ON 0x00
+#define MS_POWER_MASK 0x0C
+#define BPP_POWER_OFF 0x0F
+#define BPP_POWER_5_PERCENT_ON 0x0E
+#define BPP_POWER_10_PERCENT_ON 0x0C
+#define BPP_POWER_15_PERCENT_ON 0x08
+#define BPP_POWER_ON 0x00
+#define BPP_POWER_MASK 0x0F
+
+/* PWR_GATE_CTRL */
+#define PWR_GATE_EN 0x01
+#define LDO3318_PWR_MASK 0x06
+#define LDO_ON 0x00
+#define LDO_SUSPEND 0x04
+#define LDO_OFF 0x06
+
+/* CARD_CLK_SOURCE */
+#define CRC_FIX_CLK (0x00 << 0)
+#define CRC_VAR_CLK0 (0x01 << 0)
+#define CRC_VAR_CLK1 (0x02 << 0)
+#define SD30_FIX_CLK (0x00 << 2)
+#define SD30_VAR_CLK0 (0x01 << 2)
+#define SD30_VAR_CLK1 (0x02 << 2)
+#define SAMPLE_FIX_CLK (0x00 << 4)
+#define SAMPLE_VAR_CLK0 (0x01 << 4)
+#define SAMPLE_VAR_CLK1 (0x02 << 4)
+
+#define MS_CFG 0xFD40
+#define MS_TPC 0xFD41
+#define MS_TRANS_CFG 0xFD42
+#define MS_TRANSFER 0xFD43
+#define MS_INT_REG 0xFD44
+#define MS_BYTE_CNT 0xFD45
+#define MS_SECTOR_CNT_L 0xFD46
+#define MS_SECTOR_CNT_H 0xFD47
+#define MS_DBUS_H 0xFD48
+
+#define SD_CFG1 0xFDA0
+#define SD_CFG2 0xFDA1
+#define SD_CFG3 0xFDA2
+#define SD_STAT1 0xFDA3
+#define SD_STAT2 0xFDA4
+#define SD_BUS_STAT 0xFDA5
+#define SD_PAD_CTL 0xFDA6
+#define SD_SAMPLE_POINT_CTL 0xFDA7
+#define SD_PUSH_POINT_CTL 0xFDA8
+#define SD_CMD0 0xFDA9
+#define SD_CMD1 0xFDAA
+#define SD_CMD2 0xFDAB
+#define SD_CMD3 0xFDAC
+#define SD_CMD4 0xFDAD
+#define SD_CMD5 0xFDAE
+#define SD_BYTE_CNT_L 0xFDAF
+#define SD_BYTE_CNT_H 0xFDB0
+#define SD_BLOCK_CNT_L 0xFDB1
+#define SD_BLOCK_CNT_H 0xFDB2
+#define SD_TRANSFER 0xFDB3
+#define SD_CMD_STATE 0xFDB5
+#define SD_DATA_STATE 0xFDB6
+
+#define SRCTL 0xFC13
+
+#define DCM_DRP_CTL 0xFC23
+#define DCM_DRP_TRIG 0xFC24
+#define DCM_DRP_CFG 0xFC25
+#define DCM_DRP_WR_DATA_L 0xFC26
+#define DCM_DRP_WR_DATA_H 0xFC27
+#define DCM_DRP_RD_DATA_L 0xFC28
+#define DCM_DRP_RD_DATA_H 0xFC29
+#define SD_VPCLK0_CTL 0xFC2A
+#define SD_VPCLK1_CTL 0xFC2B
+#define SD_DCMPS0_CTL 0xFC2C
+#define SD_DCMPS1_CTL 0xFC2D
+#define SD_VPTX_CTL SD_VPCLK0_CTL
+#define SD_VPRX_CTL SD_VPCLK1_CTL
+#define SD_DCMPS_TX_CTL SD_DCMPS0_CTL
+#define SD_DCMPS_RX_CTL SD_DCMPS1_CTL
+#define CARD_CLK_SOURCE 0xFC2E
+
+#define CARD_PWR_CTL 0xFD50
+#define CARD_CLK_SWITCH 0xFD51
+#define CARD_SHARE_MODE 0xFD52
+#define CARD_DRIVE_SEL 0xFD53
+#define CARD_STOP 0xFD54
+#define CARD_OE 0xFD55
+#define CARD_AUTO_BLINK 0xFD56
+#define CARD_GPIO_DIR 0xFD57
+#define CARD_GPIO 0xFD58
+#define CARD_DATA_SOURCE 0xFD5B
+#define CARD_SELECT 0xFD5C
+#define SD30_DRIVE_SEL 0xFD5E
+#define CARD_CLK_EN 0xFD69
+#define SDIO_CTRL 0xFD6B
+#define CD_PAD_CTL 0xFD73
+
+#define FPDCTL 0xFC00
+#define PDINFO 0xFC01
+
+#define CLK_CTL 0xFC02
+#define CLK_DIV 0xFC03
+#define CLK_SEL 0xFC04
+
+#define SSC_DIV_N_0 0xFC0F
+#define SSC_DIV_N_1 0xFC10
+#define SSC_CTL1 0xFC11
+#define SSC_CTL2 0xFC12
+
+#define RCCTL 0xFC14
+
+#define FPGA_PULL_CTL 0xFC1D
+#define OLT_LED_CTL 0xFC1E
+#define GPIO_CTL 0xFC1F
+
+#define LDO_CTL 0xFC1E
+#define SYS_VER 0xFC32
+
+#define CARD_PULL_CTL1 0xFD60
+#define CARD_PULL_CTL2 0xFD61
+#define CARD_PULL_CTL3 0xFD62
+#define CARD_PULL_CTL4 0xFD63
+#define CARD_PULL_CTL5 0xFD64
+#define CARD_PULL_CTL6 0xFD65
+
+/* PCI Express Related Registers */
+#define IRQEN0 0xFE20
+#define IRQSTAT0 0xFE21
+#define IRQEN1 0xFE22
+#define IRQSTAT1 0xFE23
+#define TLPRIEN 0xFE24
+#define TLPRISTAT 0xFE25
+#define TLPTIEN 0xFE26
+#define TLPTISTAT 0xFE27
+#define DMATC0 0xFE28
+#define DMATC1 0xFE29
+#define DMATC2 0xFE2A
+#define DMATC3 0xFE2B
+#define DMACTL 0xFE2C
+#define BCTL 0xFE2D
+#define RBBC0 0xFE2E
+#define RBBC1 0xFE2F
+#define RBDAT 0xFE30
+#define RBCTL 0xFE34
+#define CFGADDR0 0xFE35
+#define CFGADDR1 0xFE36
+#define CFGDATA0 0xFE37
+#define CFGDATA1 0xFE38
+#define CFGDATA2 0xFE39
+#define CFGDATA3 0xFE3A
+#define CFGRWCTL 0xFE3B
+#define PHYRWCTL 0xFE3C
+#define PHYDATA0 0xFE3D
+#define PHYDATA1 0xFE3E
+#define PHYADDR 0xFE3F
+#define MSGRXDATA0 0xFE40
+#define MSGRXDATA1 0xFE41
+#define MSGRXDATA2 0xFE42
+#define MSGRXDATA3 0xFE43
+#define MSGTXDATA0 0xFE44
+#define MSGTXDATA1 0xFE45
+#define MSGTXDATA2 0xFE46
+#define MSGTXDATA3 0xFE47
+#define MSGTXCTL 0xFE48
+#define PETXCFG 0xFE49
+
+#define CDRESUMECTL 0xFE52
+#define WAKE_SEL_CTL 0xFE54
+#define PME_FORCE_CTL 0xFE56
+#define ASPM_FORCE_CTL 0xFE57
+#define PM_CLK_FORCE_CTL 0xFE58
+#define PERST_GLITCH_WIDTH 0xFE5C
+#define CHANGE_LINK_STATE 0xFE5B
+#define RESET_LOAD_REG 0xFE5E
+#define EFUSE_CONTENT 0xFE5F
+#define HOST_SLEEP_STATE 0xFE60
+#define SDIO_CFG 0xFE70
+
+#define NFTS_TX_CTRL 0xFE72
+
+#define PWR_GATE_CTRL 0xFE75
+#define PWD_SUSPEND_EN 0xFE76
+#define LDO_PWR_SEL 0xFE78
+
+#define DUMMY_REG_RESET_0 0xFE90
+
+/* Memory mapping */
+#define SRAM_BASE 0xE600
+#define RBUF_BASE 0xF400
+#define PPBUF_BASE1 0xF800
+#define PPBUF_BASE2 0xFA00
+#define IMAGE_FLAG_ADDR0 0xCE80
+#define IMAGE_FLAG_ADDR1 0xCE81
+
+#define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0)
+
+struct rtsx_pcr;
+
+struct pcr_handle {
+ struct rtsx_pcr *pcr;
+};
+
+struct pcr_ops {
+ int (*extra_init_hw)(struct rtsx_pcr *pcr);
+ int (*optimize_phy)(struct rtsx_pcr *pcr);
+ int (*turn_on_led)(struct rtsx_pcr *pcr);
+ int (*turn_off_led)(struct rtsx_pcr *pcr);
+ int (*enable_auto_blink)(struct rtsx_pcr *pcr);
+ int (*disable_auto_blink)(struct rtsx_pcr *pcr);
+ int (*card_power_on)(struct rtsx_pcr *pcr, int card);
+ int (*card_power_off)(struct rtsx_pcr *pcr, int card);
+ unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr);
+};
+
+enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN};
+
+struct rtsx_pcr {
+ struct pci_dev *pci;
+ unsigned int id;
+
+ /* pci resources */
+ unsigned long addr;
+ void __iomem *remap_addr;
+ int irq;
+
+ /* host reserved buffer */
+ void *rtsx_resv_buf;
+ dma_addr_t rtsx_resv_buf_addr;
+
+ void *host_cmds_ptr;
+ dma_addr_t host_cmds_addr;
+ int ci;
+
+ void *host_sg_tbl_ptr;
+ dma_addr_t host_sg_tbl_addr;
+ int sgi;
+
+ u32 bier;
+ char trans_result;
+
+ unsigned int card_inserted;
+ unsigned int card_removed;
+
+ struct delayed_work carddet_work;
+ struct delayed_work idle_work;
+
+ spinlock_t lock;
+ struct mutex pcr_mutex;
+ struct completion *done;
+ struct completion *finish_me;
+
+ unsigned int cur_clock;
+ bool ms_pmos;
+ bool remove_pci;
+ bool msi_en;
+
+#define EXTRA_CAPS_SD_SDR50 (1 << 0)
+#define EXTRA_CAPS_SD_SDR104 (1 << 1)
+#define EXTRA_CAPS_SD_DDR50 (1 << 2)
+#define EXTRA_CAPS_MMC_HSDDR (1 << 3)
+#define EXTRA_CAPS_MMC_HS200 (1 << 4)
+#define EXTRA_CAPS_MMC_8BIT (1 << 5)
+ u32 extra_caps;
+
+#define IC_VER_A 0
+#define IC_VER_B 1
+#define IC_VER_C 2
+#define IC_VER_D 3
+ u8 ic_version;
+
+ const u32 *sd_pull_ctl_enable_tbl;
+ const u32 *sd_pull_ctl_disable_tbl;
+ const u32 *ms_pull_ctl_enable_tbl;
+ const u32 *ms_pull_ctl_disable_tbl;
+
+ const struct pcr_ops *ops;
+ enum PDEV_STAT state;
+
+ int num_slots;
+ struct rtsx_slot *slots;
+};
+
+#define CHK_PCI_PID(pcr, pid) ((pcr)->pci->device == (pid))
+#define PCI_VID(pcr) ((pcr)->pci->vendor)
+#define PCI_PID(pcr) ((pcr)->pci->device)
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr);
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data);
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data);
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr);
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+ u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+ int num_sg, bool read, int timeout);
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+ u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
+
+static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
+{
+ return (u8 *)(pcr->host_cmds_ptr);
+}
+
+#endif
diff --git a/include/linux/mman.h b/include/linux/mman.h
index d09dde1e57fb..9aa863da287f 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -11,6 +11,8 @@ extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
extern struct percpu_counter vm_committed_as;
+unsigned long vm_memory_committed(void);
+
static inline void vm_acct_memory(long pages)
{
percpu_counter_add(&vm_committed_as, pages);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 943550dfe9ea..5c69315d60cc 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -85,6 +85,7 @@ struct mmc_ext_csd {
bool boot_ro_lockable;
u8 raw_exception_status; /* 53 */
u8 raw_partition_support; /* 160 */
+ u8 raw_rpmb_size_mult; /* 168 */
u8 raw_erased_mem_count; /* 181 */
u8 raw_ext_csd_structure; /* 194 */
u8 raw_card_type; /* 196 */
@@ -206,6 +207,7 @@ struct mmc_part {
#define MMC_BLK_DATA_AREA_MAIN (1<<0)
#define MMC_BLK_DATA_AREA_BOOT (1<<1)
#define MMC_BLK_DATA_AREA_GP (1<<2)
+#define MMC_BLK_DATA_AREA_RPMB (1<<3)
};
/*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 9b9cdafc7737..5bf7c2274fcb 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -170,6 +170,8 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
+extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+ bool is_rel_write);
extern int mmc_hw_reset(struct mmc_host *host);
extern int mmc_hw_reset_check(struct mmc_host *host);
extern int mmc_can_reset(struct mmc_card *card);
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 96531664a061..34be4f47293c 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -229,8 +229,9 @@ struct dw_mci_board {
u32 quirks; /* Workaround / Quirk flags */
unsigned int bus_hz; /* Clock speed at the cclk_in pad */
- unsigned int caps; /* Capabilities */
- unsigned int caps2; /* More capabilities */
+ u32 caps; /* Capabilities */
+ u32 caps2; /* More capabilities */
+ u32 pm_caps; /* PM capabilities */
/*
* Override fifo depth. If 0, autodetect it from the FIFOTH register,
* but note that this may not be reliable after a bootloader has used
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 7abb0e1f7bda..61a10c17aabd 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -53,12 +53,12 @@ struct mmc_ios {
#define MMC_TIMING_LEGACY 0
#define MMC_TIMING_MMC_HS 1
#define MMC_TIMING_SD_HS 2
-#define MMC_TIMING_UHS_SDR12 MMC_TIMING_LEGACY
-#define MMC_TIMING_UHS_SDR25 MMC_TIMING_SD_HS
-#define MMC_TIMING_UHS_SDR50 3
-#define MMC_TIMING_UHS_SDR104 4
-#define MMC_TIMING_UHS_DDR50 5
-#define MMC_TIMING_MMC_HS200 6
+#define MMC_TIMING_UHS_SDR12 3
+#define MMC_TIMING_UHS_SDR25 4
+#define MMC_TIMING_UHS_SDR50 5
+#define MMC_TIMING_UHS_SDR104 6
+#define MMC_TIMING_UHS_DDR50 7
+#define MMC_TIMING_MMC_HS200 8
#define MMC_SDR_MODE 0
#define MMC_1_2V_DDR_MODE 1
@@ -136,6 +136,7 @@ struct mmc_host_ops {
void (*enable_preset_value)(struct mmc_host *host, bool enable);
int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
void (*hw_reset)(struct mmc_host *host);
+ void (*card_event)(struct mmc_host *host);
};
struct mmc_card;
@@ -211,7 +212,7 @@ struct mmc_host {
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
- unsigned long caps; /* Host capabilities */
+ u32 caps; /* Host capabilities */
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
#define MMC_CAP_MMC_HIGHSPEED (1 << 1) /* Can do MMC high-speed timing */
@@ -241,7 +242,7 @@ struct mmc_host {
#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */
#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */
- unsigned int caps2; /* More host capabilities */
+ u32 caps2; /* More host capabilities */
#define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
#define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 01e4b394029b..94d532e41c61 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -286,6 +286,7 @@ struct _mmc_csd {
#define EXT_CSD_BKOPS_START 164 /* W */
#define EXT_CSD_SANITIZE_START 165 /* W */
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
+#define EXT_CSD_RPMB_MULT 168 /* RO */
#define EXT_CSD_BOOT_WP 173 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_PART_CONFIG 179 /* R/W */
@@ -339,6 +340,7 @@ struct _mmc_csd {
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
+#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
diff --git a/include/linux/mmc/mxs-mmc.h b/include/linux/mmc/mxs-mmc.h
deleted file mode 100644
index 7c2ad3a7f2f3..000000000000
--- a/include/linux/mmc/mxs-mmc.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_MMC_MXS_MMC_H__
-#define __LINUX_MMC_MXS_MMC_H__
-
-struct mxs_mmc_platform_data {
- int wp_gpio; /* write protect pin */
- unsigned int flags;
-#define SLOTF_4_BIT_CAPABLE (1 << 0)
-#define SLOTF_8_BIT_CAPABLE (1 << 1)
-};
-
-#endif /* __LINUX_MMC_MXS_MMC_H__ */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 1edcb4dad8c4..4bbc3301fbbf 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -92,6 +92,8 @@ struct sdhci_host {
#define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0)
#define SDHCI_QUIRK2_HOST_NO_CMD23 (1<<1)
+/* The system physically doesn't support 1.8v, even if the host does */
+#define SDHCI_QUIRK2_NO_1_8_V (1<<2)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
@@ -158,8 +160,8 @@ struct sdhci_host {
struct timer_list timer; /* Timer for timeouts */
- unsigned int caps; /* Alternative CAPABILITY_0 */
- unsigned int caps1; /* Alternative CAPABILITY_1 */
+ u32 caps; /* Alternative CAPABILITY_0 */
+ u32 caps1; /* Alternative CAPABILITY_1 */
unsigned int ocr_avail_sdio; /* OCR bit masks */
unsigned int ocr_avail_sd;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f8eda0276f03..a848ffc327f4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1488,6 +1488,9 @@ struct napi_gro_cb {
/* Used in ipv6_gro_receive() */
int proto;
+
+ /* used in skb_gro_receive() slow path */
+ struct sk_buff *last;
};
#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
diff --git a/include/linux/of.h b/include/linux/of.h
index b4e50d56fc74..60053bd7e79a 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -46,7 +46,7 @@ struct device_node {
const char *name;
const char *type;
phandle phandle;
- char *full_name;
+ const char *full_name;
struct property *properties;
struct property *deadprops; /* removed properties */
@@ -60,7 +60,7 @@ struct device_node {
unsigned long _flags;
void *data;
#if defined(CONFIG_SPARC)
- char *path_component_name;
+ const char *path_component_name;
unsigned int unique_id;
struct of_irq_controller *irq_trans;
#endif
@@ -88,14 +88,14 @@ static inline void of_node_put(struct device_node *node) { }
#ifdef CONFIG_OF
/* Pointer for first entry in chain of all nodes. */
-extern struct device_node *allnodes;
+extern struct device_node *of_allnodes;
extern struct device_node *of_chosen;
extern struct device_node *of_aliases;
extern rwlock_t devtree_lock;
static inline bool of_have_populated_dt(void)
{
- return allnodes != NULL;
+ return of_allnodes != NULL;
}
static inline bool of_node_is_root(const struct device_node *node)
@@ -179,11 +179,22 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
#define for_each_compatible_node(dn, type, compatible) \
for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
dn = of_find_compatible_node(dn, type, compatible))
-extern struct device_node *of_find_matching_node(struct device_node *from,
- const struct of_device_id *matches);
+extern struct device_node *of_find_matching_node_and_match(
+ struct device_node *from,
+ const struct of_device_id *matches,
+ const struct of_device_id **match);
+static inline struct device_node *of_find_matching_node(
+ struct device_node *from,
+ const struct of_device_id *matches)
+{
+ return of_find_matching_node_and_match(from, matches, NULL);
+}
#define for_each_matching_node(dn, matches) \
for (dn = of_find_matching_node(NULL, matches); dn; \
dn = of_find_matching_node(dn, matches))
+#define for_each_matching_node_and_match(dn, matches, match) \
+ for (dn = of_find_matching_node_and_match(NULL, matches, match); \
+ dn; dn = of_find_matching_node_and_match(dn, matches, match))
extern struct device_node *of_find_node_by_path(const char *path);
extern struct device_node *of_find_node_by_phandle(phandle handle);
extern struct device_node *of_get_parent(const struct device_node *node);
@@ -223,6 +234,10 @@ extern struct device_node *of_find_node_with_property(
extern struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp);
+extern int of_property_read_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values, size_t sz);
+extern int of_property_read_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values, size_t sz);
extern int of_property_read_u32_array(const struct device_node *np,
const char *propname,
u32 *out_values,
@@ -255,7 +270,7 @@ extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
const struct of_device_id *matches, const struct device_node *node);
extern int of_modalias_node(struct device_node *node, char *modalias, int len);
-extern struct device_node *of_parse_phandle(struct device_node *np,
+extern struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name,
int index);
extern int of_parse_phandle_with_args(struct device_node *np,
@@ -364,6 +379,18 @@ static inline struct device_node *of_find_compatible_node(
return NULL;
}
+static inline int of_property_read_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values, size_t sz)
+{
+ return -ENOSYS;
+}
+
+static inline int of_property_read_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values, size_t sz)
+{
+ return -ENOSYS;
+}
+
static inline int of_property_read_u32_array(const struct device_node *np,
const char *propname,
u32 *out_values, size_t sz)
@@ -411,7 +438,7 @@ static inline int of_property_match_string(struct device_node *np,
return -ENOSYS;
}
-static inline struct device_node *of_parse_phandle(struct device_node *np,
+static inline struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name,
int index)
{
@@ -470,6 +497,20 @@ static inline bool of_property_read_bool(const struct device_node *np,
return prop ? true : false;
}
+static inline int of_property_read_u8(const struct device_node *np,
+ const char *propname,
+ u8 *out_value)
+{
+ return of_property_read_u8_array(np, propname, out_value, 1);
+}
+
+static inline int of_property_read_u16(const struct device_node *np,
+ const char *propname,
+ u16 *out_value)
+{
+ return of_property_read_u16_array(np, propname, out_value, 1);
+}
+
static inline int of_property_read_u32(const struct device_node *np,
const char *propname,
u32 *out_value)
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index e20e3af68fb6..0506eb53519b 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -42,10 +42,12 @@ static inline struct device_node *of_find_matching_node_by_address(
{
return NULL;
}
+#ifndef of_iomap
static inline void __iomem *of_iomap(struct device_node *device, int index)
{
return NULL;
}
+#endif
static inline const __be32 *of_get_address(struct device_node *dev, int index,
u64 *size, unsigned int *flags)
{
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ee2179546c63..d03d2463efac 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -588,7 +588,7 @@ struct pci_driver {
* in a generic manner.
*/
#define DEFINE_PCI_DEVICE_TABLE(_table) \
- const struct pci_device_id _table[] __devinitconst
+ const struct pci_device_id _table[]
/**
* PCI_DEVICE - macro used to describe a specific pci device
@@ -686,7 +686,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
void pci_bus_release_busn_res(struct pci_bus *b);
-struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
@@ -941,10 +941,8 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev);
/* Functions for PCI Hotplug drivers to use */
int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
-#ifdef CONFIG_HOTPLUG
unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge);
unsigned int pci_rescan_bus(struct pci_bus *bus);
-#endif
/* Vital product data routines */
ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
@@ -1580,7 +1578,7 @@ extern int pci_pci_problems;
extern unsigned long pci_cardbus_io_size;
extern unsigned long pci_cardbus_mem_size;
-extern u8 __devinitdata pci_dfl_cache_line_size;
+extern u8 pci_dfl_cache_line_size;
extern u8 pci_cache_line_size;
extern unsigned long pci_hotplug_io_size;
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
index 250a4acddb2b..bd1e86071e57 100644
--- a/include/linux/percpu-rwsem.h
+++ b/include/linux/percpu-rwsem.h
@@ -13,7 +13,7 @@ struct percpu_rw_semaphore {
};
#define light_mb() barrier()
-#define heavy_mb() synchronize_sched()
+#define heavy_mb() synchronize_sched_expedited()
static inline void percpu_down_read(struct percpu_rw_semaphore *p)
{
@@ -51,7 +51,7 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)
{
mutex_lock(&p->mtx);
p->locked = true;
- synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */
+ synchronize_sched_expedited(); /* make sure that all readers exit the rcu_read_lock_sched region */
while (__percpu_count(p->counters))
msleep(1);
heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 4f0abb9f1c09..47a1bdd88878 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -46,11 +46,11 @@
* @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
* (open emitter). Sending this config will enabale open drain mode, the
* argument is ignored.
+ * @PIN_CONFIG_INPUT_SCHMITT_DISABLE: disable schmitt-trigger mode on the pin.
* @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
* schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
* the threshold value is given on a custom format as argument when
- * setting pins to this mode. The argument zero turns the schmitt trigger
- * off.
+ * setting pins to this mode.
* @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
* which means it will wait for signals to settle when reading inputs. The
* argument gives the debounce time on a custom format. Setting the
@@ -74,6 +74,7 @@ enum pin_config_param {
PIN_CONFIG_DRIVE_PUSH_PULL,
PIN_CONFIG_DRIVE_OPEN_DRAIN,
PIN_CONFIG_DRIVE_OPEN_SOURCE,
+ PIN_CONFIG_INPUT_SCHMITT_DISABLE,
PIN_CONFIG_INPUT_SCHMITT,
PIN_CONFIG_INPUT_DEBOUNCE,
PIN_CONFIG_POWER_SOURCE,
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 7d087f03e91e..04d6700d99af 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -134,6 +134,25 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *ranges,
unsigned nranges);
+extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range);
+
+extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+ struct pinctrl_gpio_range *range);
+extern struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+ unsigned int pin);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
#else
diff --git a/include/linux/platform_data/ads7828.h b/include/linux/platform_data/ads7828.h
new file mode 100644
index 000000000000..3245f45f9d77
--- /dev/null
+++ b/include/linux/platform_data/ads7828.h
@@ -0,0 +1,29 @@
+/*
+ * TI ADS7828 A/D Converter platform data definition
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * For further information, see the Documentation/hwmon/ads7828 file.
+ *
+ * This program is free software; you can 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 _PDATA_ADS7828_H
+#define _PDATA_ADS7828_H
+
+/**
+ * struct ads7828_platform_data - optional ADS7828 connectivity info
+ * @diff_input: Differential input mode.
+ * @ext_vref: Use an external voltage reference.
+ * @vref_mv: Voltage reference value, if external.
+ */
+struct ads7828_platform_data {
+ bool diff_input;
+ bool ext_vref;
+ unsigned int vref_mv;
+};
+
+#endif /* _PDATA_ADS7828_H */
diff --git a/include/linux/platform_data/clk-integrator.h b/include/linux/platform_data/clk-integrator.h
index 83fe9c283bb8..280edac9d0a5 100644
--- a/include/linux/platform_data/clk-integrator.h
+++ b/include/linux/platform_data/clk-integrator.h
@@ -1 +1,3 @@
void integrator_clk_init(bool is_cp);
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
+void integrator_impd1_clk_exit(unsigned int id);
diff --git a/include/linux/platform_data/gpio-ts5500.h b/include/linux/platform_data/gpio-ts5500.h
new file mode 100644
index 000000000000..b10d11c9bb49
--- /dev/null
+++ b/include/linux/platform_data/gpio-ts5500.h
@@ -0,0 +1,27 @@
+/*
+ * GPIO (DIO) header for Technologic Systems TS-5500
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ * Vivien Didelot <vivien.didelot@savoirfairelinux.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 _PDATA_GPIO_TS5500_H
+#define _PDATA_GPIO_TS5500_H
+
+/**
+ * struct ts5500_dio_platform_data - TS-5500 pin block configuration
+ * @base: The GPIO base number to use.
+ * @strap: The only pin connected to an interrupt in a block is input-only.
+ * If you need a bidirectional line which can trigger an IRQ, you
+ * may strap it with an in/out pin. This flag indicates this case.
+ */
+struct ts5500_dio_platform_data {
+ int base;
+ bool strap;
+};
+
+#endif /* _PDATA_GPIO_TS5500_H */
diff --git a/include/linux/platform_data/pinctrl-coh901.h b/include/linux/platform_data/pinctrl-coh901.h
index 30dea251b835..dfbc65d10484 100644
--- a/include/linux/platform_data/pinctrl-coh901.h
+++ b/include/linux/platform_data/pinctrl-coh901.h
@@ -13,14 +13,10 @@
* struct u300_gpio_platform - U300 GPIO platform data
* @ports: number of GPIO block ports
* @gpio_base: first GPIO number for this block (use a free range)
- * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
- * @pinctrl_device: pin control device to spawn as child
*/
struct u300_gpio_platform {
u8 ports;
int gpio_base;
- int gpio_irq_base;
- struct platform_device *pinctrl_device;
};
#endif /* __MACH_U300_GPIO_U300_H */
diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/include/linux/platform_data/pinctrl-nomadik.h
index 3b8ec60af351..f73b2f0c55b7 100644
--- a/arch/arm/plat-nomadik/include/plat/pincfg.h
+++ b/include/linux/platform_data/pinctrl-nomadik.h
@@ -1,16 +1,17 @@
/*
- * Copyright (C) ST-Ericsson SA 2010
+ * Structures and registers for GPIO access in the Nomadik SoC
*
- * License terms: GNU General Public License, version 2
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * Copyright (C) 2008 STMicroelectronics
+ * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
*
- * Based on arch/arm/mach-pxa/include/mach/mfp.h:
- * Copyright (C) 2007 Marvell International Ltd.
- * eric miao <eric.miao@marvell.com>
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
-#ifndef __PLAT_PINCFG_H
-#define __PLAT_PINCFG_H
+#ifndef __PLAT_NOMADIK_GPIO
+#define __PLAT_NOMADIK_GPIO
/*
* pin configurations are represented by 32-bit integers:
@@ -166,8 +167,100 @@ typedef unsigned long pin_cfg_t;
(PIN_CFG_DEFAULT |\
(PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT 0x00
+#define NMK_GPIO_DATS 0x04
+#define NMK_GPIO_DATC 0x08
+#define NMK_GPIO_PDIS 0x0c
+#define NMK_GPIO_DIR 0x10
+#define NMK_GPIO_DIRS 0x14
+#define NMK_GPIO_DIRC 0x18
+#define NMK_GPIO_SLPC 0x1c
+#define NMK_GPIO_AFSLA 0x20
+#define NMK_GPIO_AFSLB 0x24
+#define NMK_GPIO_LOWEMI 0x28
+
+#define NMK_GPIO_RIMSC 0x40
+#define NMK_GPIO_FIMSC 0x44
+#define NMK_GPIO_IS 0x48
+#define NMK_GPIO_IC 0x4c
+#define NMK_GPIO_RWIMSC 0x50
+#define NMK_GPIO_FWIMSC 0x54
+#define NMK_GPIO_WKS 0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL 0x60
+
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO 0
+#define NMK_GPIO_ALT_A 1
+#define NMK_GPIO_ALT_B 2
+#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1 ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2 ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3 ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4 ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+ NMK_GPIO_PULL_NONE,
+ NMK_GPIO_PULL_UP,
+ NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+ NMK_GPIO_SLPM_INPUT,
+ NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+ NMK_GPIO_SLPM_NOCHANGE,
+ NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+/* Older deprecated pin config API that should go away soon */
extern int nmk_config_pin(pin_cfg_t cfg, bool sleep);
extern int nmk_config_pins(pin_cfg_t *cfgs, int num);
extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num);
-
+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);
+extern void nmk_gpio_wakeups_resume(void);
+
+extern void nmk_gpio_clocks_enable(void);
+extern void nmk_gpio_clocks_disable(void);
+
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+ char *name;
+ int first_gpio;
+ int first_irq;
+ int num_gpio;
+ u32 (*get_secondary_status)(unsigned int bank);
+ void (*set_ioforce)(bool enable);
+ bool supports_sleepmode;
+};
+
+#endif /* __PLAT_NOMADIK_GPIO */
diff --git a/include/linux/platform_data/pxa_sdhci.h b/include/linux/platform_data/pxa_sdhci.h
index 59acd987ed34..27d3156d093a 100644
--- a/include/linux/platform_data/pxa_sdhci.h
+++ b/include/linux/platform_data/pxa_sdhci.h
@@ -38,6 +38,7 @@
* @max_speed: the maximum speed supported
* @host_caps: Standard MMC host capabilities bit field.
* @quirks: quirks of platfrom
+ * @quirks2: quirks2 of platfrom
* @pm_caps: pm_caps of platfrom
*/
struct sdhci_pxa_platdata {
@@ -48,9 +49,10 @@ struct sdhci_pxa_platdata {
unsigned int ext_cd_gpio;
bool ext_cd_gpio_invert;
unsigned int max_speed;
- unsigned int host_caps;
- unsigned int host_caps2;
+ u32 host_caps;
+ u32 host_caps2;
unsigned int quirks;
+ unsigned int quirks2;
unsigned int pm_caps;
};
diff --git a/include/linux/platform_data/uio_dmem_genirq.h b/include/linux/platform_data/uio_dmem_genirq.h
new file mode 100644
index 000000000000..973c1bb32168
--- /dev/null
+++ b/include/linux/platform_data/uio_dmem_genirq.h
@@ -0,0 +1,26 @@
+/*
+ * include/linux/platform_data/uio_dmem_genirq.h
+ *
+ * Copyright (C) 2012 Damian Hobson-Garcia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _UIO_DMEM_GENIRQ_H
+#define _UIO_DMEM_GENIRQ_H
+
+#include <linux/uio_driver.h>
+
+struct uio_dmem_genirq_pdata {
+ struct uio_info uioinfo;
+ unsigned int *dynamic_region_sizes;
+ unsigned int num_dynamic_regions;
+};
+#endif /* _UIO_DMEM_GENIRQ_H */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 5711e9525a2a..a9ded9a3c175 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -55,6 +55,7 @@ extern int platform_add_devices(struct platform_device **, int);
struct platform_device_info {
struct device *parent;
+ struct acpi_dev_node acpi_node;
const char *name;
int id;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 007e687c4f69..03d7bb145311 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -546,10 +546,9 @@ struct dev_pm_info {
unsigned long active_jiffies;
unsigned long suspended_jiffies;
unsigned long accounting_timestamp;
- struct dev_pm_qos_request *pq_req;
#endif
struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */
- struct pm_qos_constraints *constraints;
+ struct dev_pm_qos *qos;
};
extern void update_pm_runtime_accounting(struct device *dev);
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 9924ea1f22e0..5a95013905c8 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -20,6 +20,13 @@ enum {
PM_QOS_NUM_CLASSES,
};
+enum pm_qos_flags_status {
+ PM_QOS_FLAGS_UNDEFINED = -1,
+ PM_QOS_FLAGS_NONE,
+ PM_QOS_FLAGS_SOME,
+ PM_QOS_FLAGS_ALL,
+};
+
#define PM_QOS_DEFAULT_VALUE -1
#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
@@ -27,14 +34,31 @@ enum {
#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0
#define PM_QOS_DEV_LAT_DEFAULT_VALUE 0
+#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
+#define PM_QOS_FLAG_REMOTE_WAKEUP (1 << 1)
+
struct pm_qos_request {
struct plist_node node;
int pm_qos_class;
struct delayed_work work; /* for pm_qos_update_request_timeout */
};
+struct pm_qos_flags_request {
+ struct list_head node;
+ s32 flags; /* Do not change to 64 bit */
+};
+
+enum dev_pm_qos_req_type {
+ DEV_PM_QOS_LATENCY = 1,
+ DEV_PM_QOS_FLAGS,
+};
+
struct dev_pm_qos_request {
- struct plist_node node;
+ enum dev_pm_qos_req_type type;
+ union {
+ struct plist_node pnode;
+ struct pm_qos_flags_request flr;
+ } data;
struct device *dev;
};
@@ -45,8 +69,8 @@ enum pm_qos_type {
};
/*
- * Note: The lockless read path depends on the CPU accessing
- * target_value atomically. Atomic access is only guaranteed on all CPU
+ * Note: The lockless read path depends on the CPU accessing target_value
+ * or effective_flags atomically. Atomic access is only guaranteed on all CPU
* types linux supports for 32 bit quantites
*/
struct pm_qos_constraints {
@@ -57,6 +81,18 @@ struct pm_qos_constraints {
struct blocking_notifier_head *notifiers;
};
+struct pm_qos_flags {
+ struct list_head list;
+ s32 effective_flags; /* Do not change to 64 bit */
+};
+
+struct dev_pm_qos {
+ struct pm_qos_constraints latency;
+ struct pm_qos_flags flags;
+ struct dev_pm_qos_request *latency_req;
+ struct dev_pm_qos_request *flags_req;
+};
+
/* Action requested to pm_qos_update_target */
enum pm_qos_req_action {
PM_QOS_ADD_REQ, /* Add a new request */
@@ -71,6 +107,9 @@ static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
enum pm_qos_req_action action, int value);
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+ struct pm_qos_flags_request *req,
+ enum pm_qos_req_action action, s32 val);
void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class,
s32 value);
void pm_qos_update_request(struct pm_qos_request *req,
@@ -86,10 +125,12 @@ int pm_qos_request_active(struct pm_qos_request *req);
s32 pm_qos_read_value(struct pm_qos_constraints *c);
#ifdef CONFIG_PM
+enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
+enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
s32 __dev_pm_qos_read_value(struct device *dev);
s32 dev_pm_qos_read_value(struct device *dev);
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
- s32 value);
+ enum dev_pm_qos_req_type type, s32 value);
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
int dev_pm_qos_add_notifier(struct device *dev,
@@ -103,12 +144,19 @@ void dev_pm_qos_constraints_destroy(struct device *dev);
int dev_pm_qos_add_ancestor_request(struct device *dev,
struct dev_pm_qos_request *req, s32 value);
#else
+static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
+ s32 mask)
+ { return PM_QOS_FLAGS_UNDEFINED; }
+static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
+ s32 mask)
+ { return PM_QOS_FLAGS_UNDEFINED; }
static inline s32 __dev_pm_qos_read_value(struct device *dev)
{ return 0; }
static inline s32 dev_pm_qos_read_value(struct device *dev)
{ return 0; }
static inline int dev_pm_qos_add_request(struct device *dev,
struct dev_pm_qos_request *req,
+ enum dev_pm_qos_req_type type,
s32 value)
{ return 0; }
static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
@@ -144,10 +192,31 @@ static inline int dev_pm_qos_add_ancestor_request(struct device *dev,
#ifdef CONFIG_PM_RUNTIME
int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value);
void dev_pm_qos_hide_latency_limit(struct device *dev);
+int dev_pm_qos_expose_flags(struct device *dev, s32 value);
+void dev_pm_qos_hide_flags(struct device *dev);
+int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set);
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev)
+{
+ return dev->power.qos->latency_req->data.pnode.prio;
+}
+
+static inline s32 dev_pm_qos_requested_flags(struct device *dev)
+{
+ return dev->power.qos->flags_req->data.flr.flags;
+}
#else
static inline int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
{ return 0; }
static inline void dev_pm_qos_hide_latency_limit(struct device *dev) {}
+static inline int dev_pm_qos_expose_flags(struct device *dev, s32 value)
+ { return 0; }
+static inline void dev_pm_qos_hide_flags(struct device *dev) {}
+static inline int dev_pm_qos_update_flags(struct device *dev, s32 m, bool set)
+ { return 0; }
+
+static inline s32 dev_pm_qos_requested_latency(struct device *dev) { return 0; }
+static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
#endif
#endif
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index c64de9dd7631..2f694f3846a9 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -46,8 +46,9 @@ struct ads7846_platform_data {
u16 debounce_rep; /* additional consecutive good readings
* required after the first two */
int gpio_pendown; /* the GPIO used to decide the pendown
- * state if get_pendown_state == NULL
- */
+ * state if get_pendown_state == NULL */
+ int gpio_pendown_debounce; /* platform specific debounce time for
+ * the gpio_pendown */
int (*get_pendown_state)(void);
int (*filter_init) (const struct ads7846_platform_data *pdata,
void **filter_data);
diff --git a/include/linux/tick.h b/include/linux/tick.h
index f37fceb69b73..1a6567b48492 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -142,4 +142,10 @@ static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; }
# endif /* !NO_HZ */
+# ifdef CONFIG_CPU_IDLE_GOV_MENU
+extern void menu_hrtimer_cancel(void);
+# else
+static inline void menu_hrtimer_cancel(void) {}
+# endif /* CONFIG_CPU_IDLE_GOV_MENU */
+
#endif
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index 171b957db743..dc004bc926c9 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel {
ADV7604_OP_CH_SEL_RBG = 5,
};
-/* Primary mode (IO register 0x01, [3:0]) */
-enum adv7604_prim_mode {
- ADV7604_PRIM_MODE_COMP = 1,
- ADV7604_PRIM_MODE_RGB = 2,
- ADV7604_PRIM_MODE_HDMI_COMP = 5,
- ADV7604_PRIM_MODE_HDMI_GR = 6,
-};
-
/* Input Color Space (IO register 0x02, [7:4]) */
enum adv7604_inp_color_space {
ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
@@ -103,9 +95,6 @@ struct adv7604_platform_data {
/* Bus rotation and reordering */
enum adv7604_op_ch_sel op_ch_sel;
- /* Primary mode */
- enum adv7604_prim_mode prim_mode;
-
/* Select output format */
enum adv7604_op_format_sel op_format_sel;
@@ -142,6 +131,16 @@ struct adv7604_platform_data {
u8 i2c_vdp;
};
+/*
+ * Mode of operation.
+ * This is used as the input argument of the s_routing video op.
+ */
+enum adv7604_mode {
+ ADV7604_MODE_COMP,
+ ADV7604_MODE_GR,
+ ADV7604_MODE_HDMI,
+};
+
#define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6feeccd83dd7..4af45e33105d 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -525,6 +525,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
int nonagle);
extern bool tcp_may_send_now(struct sock *sk);
+extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
extern void tcp_retransmit_timer(struct sock *sk);
extern void tcp_xmit_retransmit_queue(struct sock *);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 6f0ba01afe73..63445ede48bb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1351,7 +1351,7 @@ struct xfrm6_tunnel {
};
extern void xfrm_init(void);
-extern void xfrm4_init(int rt_hash_size);
+extern void xfrm4_init(void);
extern int xfrm_state_init(struct net *net);
extern void xfrm_state_fini(struct net *net);
extern void xfrm4_state_init(void);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 88fae8d20154..55367b04dc94 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -135,6 +135,8 @@ struct scsi_device {
* because we did a bus reset. */
unsigned use_10_for_rw:1; /* first try 10-byte read / write */
unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+ unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */
+ unsigned no_write_same:1; /* no WRITE SAME command */
unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */
unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */
unsigned skip_vpd_pages:1; /* do not read VPD pages */
@@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
int retries, struct scsi_sense_hdr *sshdr);
extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
int buf_len);
+extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+ unsigned int len, unsigned char opcode);
extern int scsi_device_set_state(struct scsi_device *sdev,
enum scsi_device_state state);
extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h
index 9391706e9254..d6fd8e5b14b7 100644
--- a/include/trace/events/gfpflags.h
+++ b/include/trace/events/gfpflags.h
@@ -36,6 +36,7 @@
{(unsigned long)__GFP_RECLAIMABLE, "GFP_RECLAIMABLE"}, \
{(unsigned long)__GFP_MOVABLE, "GFP_MOVABLE"}, \
{(unsigned long)__GFP_NOTRACK, "GFP_NOTRACK"}, \
+ {(unsigned long)__GFP_NO_KSWAPD, "GFP_NO_KSWAPD"}, \
{(unsigned long)__GFP_OTHER_NODE, "GFP_OTHER_NODE"} \
) : "GFP_NOWAIT"
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index e194387ef784..19e765fbfef7 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -415,3 +415,4 @@ header-y += wireless.h
header-y += x25.h
header-y += xattr.h
header-y += xfrm.h
+header-y += hw_breakpoint.h
diff --git a/include/uapi/linux/hw_breakpoint.h b/include/uapi/linux/hw_breakpoint.h
new file mode 100644
index 000000000000..b04000a2296a
--- /dev/null
+++ b/include/uapi/linux/hw_breakpoint.h
@@ -0,0 +1,30 @@
+#ifndef _UAPI_LINUX_HW_BREAKPOINT_H
+#define _UAPI_LINUX_HW_BREAKPOINT_H
+
+enum {
+ HW_BREAKPOINT_LEN_1 = 1,
+ HW_BREAKPOINT_LEN_2 = 2,
+ HW_BREAKPOINT_LEN_4 = 4,
+ HW_BREAKPOINT_LEN_8 = 8,
+};
+
+enum {
+ HW_BREAKPOINT_EMPTY = 0,
+ HW_BREAKPOINT_R = 1,
+ HW_BREAKPOINT_W = 2,
+ HW_BREAKPOINT_RW = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
+ HW_BREAKPOINT_X = 4,
+ HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
+};
+
+enum bp_type_idx {
+ TYPE_INST = 0,
+#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
+ TYPE_DATA = 0,
+#else
+ TYPE_DATA = 1,
+#endif
+ TYPE_MAX
+};
+
+#endif /* _UAPI_LINUX_HW_BREAKPOINT_H */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 42bd331ee0ab..f45657f1eb8e 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -348,11 +348,13 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
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();
+ if (cpu_online(cpu) || !cpu_present(cpu)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
idle = idle_thread_get(cpu);
if (IS_ERR(idle)) {
ret = PTR_ERR(idle);
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 9a7b487c6fe2..fe8a916507ed 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -111,14 +111,16 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
* Count the number of breakpoints of the same type and same task.
* The given event must be not on the list.
*/
-static int task_bp_pinned(struct perf_event *bp, enum bp_type_idx type)
+static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
{
struct task_struct *tsk = bp->hw.bp_target;
struct perf_event *iter;
int count = 0;
list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
- if (iter->hw.bp_target == tsk && find_slot_idx(iter) == type)
+ if (iter->hw.bp_target == tsk &&
+ find_slot_idx(iter) == type &&
+ cpu == iter->cpu)
count += hw_breakpoint_weight(iter);
}
@@ -141,7 +143,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
if (!tsk)
slots->pinned += max_task_bp_pinned(cpu, type);
else
- slots->pinned += task_bp_pinned(bp, type);
+ slots->pinned += task_bp_pinned(cpu, bp, type);
slots->flexible = per_cpu(nr_bp_flexible[type], cpu);
return;
@@ -154,7 +156,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
if (!tsk)
nr += max_task_bp_pinned(cpu, type);
else
- nr += task_bp_pinned(bp, type);
+ nr += task_bp_pinned(cpu, bp, type);
if (nr > slots->pinned)
slots->pinned = nr;
@@ -188,7 +190,7 @@ static void toggle_bp_task_slot(struct perf_event *bp, int cpu, bool enable,
int old_idx = 0;
int idx = 0;
- old_count = task_bp_pinned(bp, type);
+ old_count = task_bp_pinned(cpu, bp, type);
old_idx = old_count - 1;
idx = old_idx + weight;
diff --git a/kernel/futex.c b/kernel/futex.c
index 20ef219bbe9b..19eb089ca003 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -843,6 +843,9 @@ static void wake_futex(struct futex_q *q)
{
struct task_struct *p = q->task;
+ if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
+ return;
+
/*
* We set q->lock_ptr = NULL _before_ we wake up the task. If
* a non-futex wake up happens on another CPU then the task
@@ -1078,6 +1081,10 @@ retry_private:
plist_for_each_entry_safe(this, next, head, list) {
if (match_futex (&this->key, &key1)) {
+ if (this->pi_state || this->rt_waiter) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
wake_futex(this);
if (++ret >= nr_wake)
break;
@@ -1090,6 +1097,10 @@ retry_private:
op_ret = 0;
plist_for_each_entry_safe(this, next, head, list) {
if (match_futex (&this->key, &key2)) {
+ if (this->pi_state || this->rt_waiter) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
wake_futex(this);
if (++op_ret >= nr_wake2)
break;
@@ -1098,6 +1109,7 @@ retry_private:
ret += op_ret;
}
+out_unlock:
double_unlock_hb(hb1, hb2);
out_put_keys:
put_futex_key(&key2);
@@ -1387,9 +1399,13 @@ retry_private:
/*
* FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
* be paired with each other and no other futex ops.
+ *
+ * We should never be requeueing a futex_q with a pi_state,
+ * which is awaiting a futex_unlock_pi().
*/
if ((requeue_pi && !this->rt_waiter) ||
- (!requeue_pi && this->rt_waiter)) {
+ (!requeue_pi && this->rt_waiter) ||
+ this->pi_state) {
ret = -EINVAL;
break;
}
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 4e69e24d3d7d..96f3a1d9c379 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -177,8 +177,8 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
irq_base = irq_alloc_descs(first_irq, first_irq, size,
of_node_to_nid(of_node));
if (irq_base < 0) {
- WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
- first_irq);
+ pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+ first_irq);
irq_base = first_irq;
}
} else
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 4e316e1acf58..c01eac66c0cc 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -26,7 +26,6 @@ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
static struct kobj_attribute _name##_attr = \
__ATTR(_name, 0644, _name##_show, _name##_store)
-#if defined(CONFIG_HOTPLUG)
/* current uevent sequence number */
static ssize_t uevent_seqnum_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
@@ -54,7 +53,7 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
return count;
}
KERNEL_ATTR_RW(uevent_helper);
-#endif
+
#ifdef CONFIG_PROFILING
static ssize_t profiling_show(struct kobject *kobj,
@@ -169,10 +168,8 @@ EXPORT_SYMBOL_GPL(kernel_kobj);
static struct attribute * kernel_attrs[] = {
&fscaps_attr.attr,
-#if defined(CONFIG_HOTPLUG)
&uevent_seqnum_attr.attr,
&uevent_helper_attr.attr,
-#endif
#ifdef CONFIG_PROFILING
&profiling_attr.attr,
#endif
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
index 4646eb2c3820..767e559dfb10 100644
--- a/kernel/modsign_pubkey.c
+++ b/kernel/modsign_pubkey.c
@@ -21,10 +21,10 @@ struct key *modsign_keyring;
extern __initdata const u8 modsign_certificate_list[];
extern __initdata const u8 modsign_certificate_list_end[];
asm(".section .init.data,\"aw\"\n"
- "modsign_certificate_list:\n"
+ SYMBOL_PREFIX "modsign_certificate_list:\n"
".incbin \"signing_key.x509\"\n"
".incbin \"extra_certificates\"\n"
- "modsign_certificate_list_end:"
+ SYMBOL_PREFIX "modsign_certificate_list_end:"
);
/*
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index ea1b1df5dbb0..f2970bddc5ea 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -27,13 +27,13 @@
* - Information block
*/
struct module_signature {
- enum pkey_algo algo : 8; /* Public-key crypto algorithm */
- enum pkey_hash_algo hash : 8; /* Digest algorithm */
- enum pkey_id_type id_type : 8; /* Key identifier type */
- u8 signer_len; /* Length of signer's name */
- u8 key_id_len; /* Length of key identifier */
- u8 __pad[3];
- __be32 sig_len; /* Length of signature data */
+ u8 algo; /* Public-key crypto algorithm [enum pkey_algo] */
+ u8 hash; /* Digest algorithm [enum pkey_hash_algo] */
+ u8 id_type; /* Key identifier type [enum pkey_id_type] */
+ u8 signer_len; /* Length of signer's name */
+ u8 key_id_len; /* Length of key identifier */
+ u8 __pad[3];
+ __be32 sig_len; /* Length of signature data */
};
/*
diff --git a/kernel/power/main.c b/kernel/power/main.c
index f458238109cc..1c16f9167de1 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -59,7 +59,7 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
{
unsigned long val;
- if (strict_strtoul(buf, 10, &val))
+ if (kstrtoul(buf, 10, &val))
return -EINVAL;
if (val > 1)
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 846bd42c7ed1..9322ff7eaad6 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -213,6 +213,69 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
}
/**
+ * pm_qos_flags_remove_req - Remove device PM QoS flags request.
+ * @pqf: Device PM QoS flags set to remove the request from.
+ * @req: Request to remove from the set.
+ */
+static void pm_qos_flags_remove_req(struct pm_qos_flags *pqf,
+ struct pm_qos_flags_request *req)
+{
+ s32 val = 0;
+
+ list_del(&req->node);
+ list_for_each_entry(req, &pqf->list, node)
+ val |= req->flags;
+
+ pqf->effective_flags = val;
+}
+
+/**
+ * pm_qos_update_flags - Update a set of PM QoS flags.
+ * @pqf: Set of flags to update.
+ * @req: Request to add to the set, to modify, or to remove from the set.
+ * @action: Action to take on the set.
+ * @val: Value of the request to add or modify.
+ *
+ * Update the given set of PM QoS flags and call notifiers if the aggregate
+ * value has changed. Returns 1 if the aggregate constraint value has changed,
+ * 0 otherwise.
+ */
+bool pm_qos_update_flags(struct pm_qos_flags *pqf,
+ struct pm_qos_flags_request *req,
+ enum pm_qos_req_action action, s32 val)
+{
+ unsigned long irqflags;
+ s32 prev_value, curr_value;
+
+ spin_lock_irqsave(&pm_qos_lock, irqflags);
+
+ prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+ switch (action) {
+ case PM_QOS_REMOVE_REQ:
+ pm_qos_flags_remove_req(pqf, req);
+ break;
+ case PM_QOS_UPDATE_REQ:
+ pm_qos_flags_remove_req(pqf, req);
+ case PM_QOS_ADD_REQ:
+ req->flags = val;
+ INIT_LIST_HEAD(&req->node);
+ list_add_tail(&req->node, &pqf->list);
+ pqf->effective_flags |= val;
+ break;
+ default:
+ /* no action */
+ ;
+ }
+
+ curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags;
+
+ spin_unlock_irqrestore(&pm_qos_lock, irqflags);
+
+ return prev_value != curr_value;
+}
+
+/**
* pm_qos_request - returns current system wide qos expectation
* @pm_qos_class: identification of which qos value is requested
*
@@ -500,7 +563,7 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
} else {
ascii_value[count] = '\0';
}
- ret = strict_strtoul(ascii_value, 16, &ulval);
+ ret = kstrtoul(ascii_value, 16, &ulval);
if (ret) {
pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
return -EINVAL;
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 3c9d764eb0d8..7c33ed200410 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -126,7 +126,7 @@ static int swsusp_extents_insert(unsigned long swap_offset)
/* Figure out where to put the new node */
while (*new) {
- ext = container_of(*new, struct swsusp_extent, node);
+ ext = rb_entry(*new, struct swsusp_extent, node);
parent = *new;
if (swap_offset < ext->start) {
/* Try to merge */
diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c
index 0984a21076a3..15f60d01198b 100644
--- a/kernel/sched/auto_group.c
+++ b/kernel/sched/auto_group.c
@@ -143,15 +143,11 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag)
p->signal->autogroup = autogroup_kref_get(ag);
- if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled))
- goto out;
-
t = p;
do {
sched_move_task(t);
} while_each_thread(p, t);
-out:
unlock_task_sighand(p, &flags);
autogroup_kref_put(prev);
}
diff --git a/kernel/sched/auto_group.h b/kernel/sched/auto_group.h
index 8bd047142816..443232ebbb53 100644
--- a/kernel/sched/auto_group.h
+++ b/kernel/sched/auto_group.h
@@ -4,11 +4,6 @@
#include <linux/rwsem.h>
struct autogroup {
- /*
- * reference doesn't mean how many thread attach to this
- * autogroup now. It just stands for the number of task
- * could use this autogroup.
- */
struct kref kref;
struct task_group *tg;
struct rw_semaphore lock;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 26f65eaa01f9..33f71f37267e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -565,7 +565,7 @@ static struct ctl_table kern_table[] = {
.extra2 = &one,
},
#endif
-#ifdef CONFIG_HOTPLUG
+
{
.procname = "hotplug",
.data = &uevent_helper,
@@ -573,7 +573,7 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dostring,
},
-#endif
+
#ifdef CONFIG_CHR_DEV_SG
{
.procname = "sg-big-buff",
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index a40260885265..6f337068dc4c 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -526,6 +526,8 @@ void tick_nohz_irq_exit(void)
if (!ts->inidle)
return;
+ /* Cancel the timer because CPU already waken up from the C-states*/
+ menu_hrtimer_cancel();
__tick_nohz_idle_enter(ts);
}
@@ -621,6 +623,8 @@ void tick_nohz_idle_exit(void)
ts->inidle = 0;
+ /* Cancel the timer because CPU already waken up from the C-states*/
+ menu_hrtimer_cancel();
if (ts->idle_active || ts->tick_stopped)
now = ktime_get();
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 9d4c8d5a1f53..c8c21be11ab4 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -116,7 +116,7 @@ static unsigned long get_timestamp(int this_cpu)
return cpu_clock(this_cpu) >> 30LL; /* 2^30 ~= 10^9 */
}
-static unsigned long get_sample_period(void)
+static u64 get_sample_period(void)
{
/*
* convert watchdog_thresh from seconds to ns
@@ -125,7 +125,7 @@ static unsigned long get_sample_period(void)
* and hard thresholds) to increment before the
* hardlockup detector generates a warning
*/
- return get_softlockup_thresh() * (NSEC_PER_SEC / 5);
+ return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5);
}
/* Commands for resetting the watchdog */
@@ -368,6 +368,9 @@ static void watchdog_disable(unsigned int cpu)
{
struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
+ if (!watchdog_enabled)
+ return;
+
watchdog_set_prio(SCHED_NORMAL, 0);
hrtimer_cancel(hrtimer);
/* disable the perf event */
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 042d221d33cc..1dae900df798 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1361,8 +1361,19 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
WARN_ON_ONCE(timer->function != delayed_work_timer_fn ||
timer->data != (unsigned long)dwork);
- BUG_ON(timer_pending(timer));
- BUG_ON(!list_empty(&work->entry));
+ WARN_ON_ONCE(timer_pending(timer));
+ WARN_ON_ONCE(!list_empty(&work->entry));
+
+ /*
+ * If @delay is 0, queue @dwork->work immediately. This is for
+ * both optimization and correctness. The earliest @timer can
+ * expire is on the closest next tick and delayed_work users depend
+ * on that there's no such delay when @delay is 0.
+ */
+ if (!delay) {
+ __queue_work(cpu, wq, &dwork->work);
+ return;
+ }
timer_stats_timer_set_start_info(&dwork->timer);
@@ -1417,9 +1428,6 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
bool ret = false;
unsigned long flags;
- if (!delay)
- return queue_work_on(cpu, wq, &dwork->work);
-
/* read the comment in __queue_work() */
local_irq_save(flags);
@@ -2407,8 +2415,10 @@ static int rescuer_thread(void *__wq)
repeat:
set_current_state(TASK_INTERRUPTIBLE);
- if (kthread_should_stop())
+ if (kthread_should_stop()) {
+ __set_current_state(TASK_RUNNING);
return 0;
+ }
/*
* See whether any cpu is asking for help. Unbounded
diff --git a/lib/Makefile b/lib/Makefile
index 821a16229111..e3723c7527da 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
idr.o int_sqrt.o extable.o \
sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
proportions.o flex_proportions.o prio_heap.o ratelimit.o show_mem.o \
- is_single_threaded.o plist.o decompress.o
+ is_single_threaded.o plist.o decompress.o kobject_uevent.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
@@ -31,7 +31,6 @@ CFLAGS_kobject.o += -DDEBUG
CFLAGS_kobject_uevent.o += -DDEBUG
endif
-lib-$(CONFIG_HOTPLUG) += kobject_uevent.o
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
@@ -163,7 +162,7 @@ $(obj)/crc32table.h: $(obj)/gen_crc32table
#
obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
-$(obj)/oid_registry.c: $(obj)/oid_registry_data.c
+$(obj)/oid_registry.o: $(obj)/oid_registry_data.c
$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \
$(src)/build_OID_registry
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c
index de2c8b5a715b..5293d2433029 100644
--- a/lib/asn1_decoder.c
+++ b/lib/asn1_decoder.c
@@ -91,7 +91,7 @@ next_tag:
/* Extract the length */
len = data[dp++];
- if (len < 0x7f) {
+ if (len <= 0x7f) {
dp += len;
goto next_tag;
}
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
index 678ce4f1e124..095ab157a521 100644
--- a/lib/mpi/longlong.h
+++ b/lib/mpi/longlong.h
@@ -641,7 +641,14 @@ do { \
************** MIPS *****************
***************************************/
#if defined(__mips__) && W_TYPE_SIZE == 32
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do { \
+ UDItype __ll = (UDItype)(u) * (v); \
+ w1 = __ll >> 32; \
+ w0 = __ll; \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("multu %2,%3" \
: "=l" ((USItype)(w0)), \
@@ -666,7 +673,15 @@ do { \
************** MIPS/64 **************
***************************************/
#if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do { \
+ typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \
+ __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \
+ w1 = __ll >> 64; \
+ w0 = __ll; \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("dmultu %2,%3" \
: "=l" ((UDItype)(w0)), \
diff --git a/mm/compaction.c b/mm/compaction.c
index 9eef55838fca..694eaabaaebd 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -713,7 +713,15 @@ static void isolate_freepages(struct zone *zone,
/* Found a block suitable for isolating free pages from */
isolated = 0;
- end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
+
+ /*
+ * As pfn may not start aligned, pfn+pageblock_nr_page
+ * may cross a MAX_ORDER_NR_PAGES boundary and miss
+ * a pfn_valid check. Ensure isolate_freepages_block()
+ * only scans within a pageblock
+ */
+ end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
+ end_pfn = min(end_pfn, zone_end_pfn);
isolated = isolate_freepages_block(cc, pfn, end_pfn,
freelist, false);
nr_freepages += isolated;
diff --git a/mm/dmapool.c b/mm/dmapool.c
index c5ab33bca0a8..da1b0f0b8709 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -50,7 +50,6 @@ struct dma_pool { /* the pool */
size_t allocation;
size_t boundary;
char name[32];
- wait_queue_head_t waitq;
struct list_head pools;
};
@@ -62,8 +61,6 @@ struct dma_page { /* cacheable header for 'allocation' bytes */
unsigned int offset;
};
-#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
-
static DEFINE_MUTEX(pools_lock);
static ssize_t
@@ -172,7 +169,6 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
retval->size = size;
retval->boundary = boundary;
retval->allocation = allocation;
- init_waitqueue_head(&retval->waitq);
if (dev) {
int ret;
@@ -227,7 +223,6 @@ static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
#endif
pool_initialise_page(pool, page);
- list_add(&page->page_list, &pool->page_list);
page->in_use = 0;
page->offset = 0;
} else {
@@ -315,30 +310,21 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
might_sleep_if(mem_flags & __GFP_WAIT);
spin_lock_irqsave(&pool->lock, flags);
- restart:
list_for_each_entry(page, &pool->page_list, page_list) {
if (page->offset < pool->allocation)
goto ready;
}
- page = pool_alloc_page(pool, GFP_ATOMIC);
- if (!page) {
- if (mem_flags & __GFP_WAIT) {
- DECLARE_WAITQUEUE(wait, current);
- __set_current_state(TASK_UNINTERRUPTIBLE);
- __add_wait_queue(&pool->waitq, &wait);
- spin_unlock_irqrestore(&pool->lock, flags);
+ /* pool_alloc_page() might sleep, so temporarily drop &pool->lock */
+ spin_unlock_irqrestore(&pool->lock, flags);
- schedule_timeout(POOL_TIMEOUT_JIFFIES);
+ page = pool_alloc_page(pool, mem_flags);
+ if (!page)
+ return NULL;
- spin_lock_irqsave(&pool->lock, flags);
- __remove_wait_queue(&pool->waitq, &wait);
- goto restart;
- }
- retval = NULL;
- goto done;
- }
+ spin_lock_irqsave(&pool->lock, flags);
+ list_add(&page->page_list, &pool->page_list);
ready:
page->in_use++;
offset = page->offset;
@@ -348,7 +334,6 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
#ifdef DMAPOOL_DEBUG
memset(retval, POOL_POISON_ALLOCATED, pool->size);
#endif
- done:
spin_unlock_irqrestore(&pool->lock, flags);
return retval;
}
@@ -435,8 +420,6 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
page->in_use--;
*(int *)vaddr = page->offset;
page->offset = offset;
- if (waitqueue_active(&pool->waitq))
- wake_up_locked(&pool->waitq);
/*
* Resist a temptation to do
* if (!is_page_busy(page)) pool_free_page(pool, page);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 6c5899b9034a..8b20278be6a6 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1476,9 +1476,17 @@ int soft_offline_page(struct page *page, int flags)
{
int ret;
unsigned long pfn = page_to_pfn(page);
+ struct page *hpage = compound_trans_head(page);
if (PageHuge(page))
return soft_offline_huge_page(page, flags);
+ if (PageTransHuge(hpage)) {
+ if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) {
+ pr_info("soft offline: %#lx: failed to split THP\n",
+ pfn);
+ return -EBUSY;
+ }
+ }
ret = get_any_page(page, pfn, flags);
if (ret < 0)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d04a8a54c294..4ea600da8940 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2037,28 +2037,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old)
return new;
}
-/*
- * If *frompol needs [has] an extra ref, copy *frompol to *tompol ,
- * eliminate the * MPOL_F_* flags that require conditional ref and
- * [NOTE!!!] drop the extra ref. Not safe to reference *frompol directly
- * after return. Use the returned value.
- *
- * Allows use of a mempolicy for, e.g., multiple allocations with a single
- * policy lookup, even if the policy needs/has extra ref on lookup.
- * shmem_readahead needs this.
- */
-struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
- struct mempolicy *frompol)
-{
- if (!mpol_needs_cond_ref(frompol))
- return frompol;
-
- *tompol = *frompol;
- tompol->flags &= ~MPOL_F_SHARED; /* copy doesn't need unref */
- __mpol_put(frompol);
- return tompol;
-}
-
/* Slow path of a mempolicy comparison */
bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
{
diff --git a/mm/mmap.c b/mm/mmap.c
index 9a796c41e7d9..7d416055f08c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -89,6 +89,20 @@ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
struct percpu_counter vm_committed_as ____cacheline_aligned_in_smp;
/*
+ * The global memory commitment made in the system can be a metric
+ * that can be used to drive ballooning decisions when Linux is hosted
+ * as a guest. On Hyper-V, the host implements a policy engine for dynamically
+ * balancing memory across competing virtual machines that are hosted.
+ * Several metrics drive this policy engine including the guest reported
+ * memory commitment.
+ */
+unsigned long vm_memory_committed(void)
+{
+ return percpu_counter_read_positive(&vm_committed_as);
+}
+EXPORT_SYMBOL_GPL(vm_memory_committed);
+
+/*
* Check that a process has enough memory to allocate a new virtual
* mapping. 0 means there is enough memory for the allocation to
* succeed and -ENOMEM implies there is not.
diff --git a/mm/nommu.c b/mm/nommu.c
index 45131b41bcdb..79c3cac87afa 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -66,6 +66,21 @@ int heap_stack_gap = 0;
atomic_long_t mmap_pages_allocated;
+/*
+ * The global memory commitment made in the system can be a metric
+ * that can be used to drive ballooning decisions when Linux is hosted
+ * as a guest. On Hyper-V, the host implements a policy engine for dynamically
+ * balancing memory across competing virtual machines that are hosted.
+ * Several metrics drive this policy engine including the guest reported
+ * memory commitment.
+ */
+unsigned long vm_memory_committed(void)
+{
+ return percpu_counter_read_positive(&vm_committed_as);
+}
+
+EXPORT_SYMBOL_GPL(vm_memory_committed);
+
EXPORT_SYMBOL(mem_map);
EXPORT_SYMBOL(num_physpages);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7bb35ac0964a..7e208f0ad68c 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
mt = get_pageblock_migratetype(page);
if (unlikely(mt != MIGRATE_ISOLATE))
- __mod_zone_freepage_state(zone, -(1UL << order), mt);
+ __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
if (alloc_order != order)
expand(zone, page, alloc_order, order,
@@ -1422,7 +1422,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
}
}
- return 1UL << order;
+ return 1UL << alloc_order;
}
/*
@@ -2416,8 +2416,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
goto nopage;
restart:
- wake_all_kswapd(order, zonelist, high_zoneidx,
- zone_idx(preferred_zone));
+ if (!(gfp_mask & __GFP_NO_KSWAPD))
+ wake_all_kswapd(order, zonelist, high_zoneidx,
+ zone_idx(preferred_zone));
/*
* OK, we're below the kswapd watermark and have kicked background
@@ -2494,7 +2495,7 @@ rebalance:
* system then fail the allocation instead of entering direct reclaim.
*/
if ((deferred_compaction || contended_compaction) &&
- (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE)
+ (gfp_mask & __GFP_NO_KSWAPD))
goto nopage;
/* Try direct reclaim and then allocating */
diff --git a/mm/shmem.c b/mm/shmem.c
index 89341b658bd0..50c5b8f3a359 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -910,25 +910,29 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
struct shmem_inode_info *info, pgoff_t index)
{
- struct mempolicy mpol, *spol;
struct vm_area_struct pvma;
-
- spol = mpol_cond_copy(&mpol,
- mpol_shared_policy_lookup(&info->policy, index));
+ struct page *page;
/* Create a pseudo vma that just contains the policy */
pvma.vm_start = 0;
/* Bias interleave by inode number to distribute better across nodes */
pvma.vm_pgoff = index + info->vfs_inode.i_ino;
pvma.vm_ops = NULL;
- pvma.vm_policy = spol;
- return swapin_readahead(swap, gfp, &pvma, 0);
+ pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
+
+ page = swapin_readahead(swap, gfp, &pvma, 0);
+
+ /* Drop reference taken by mpol_shared_policy_lookup() */
+ mpol_cond_put(pvma.vm_policy);
+
+ return page;
}
static struct page *shmem_alloc_page(gfp_t gfp,
struct shmem_inode_info *info, pgoff_t index)
{
struct vm_area_struct pvma;
+ struct page *page;
/* Create a pseudo vma that just contains the policy */
pvma.vm_start = 0;
@@ -937,10 +941,12 @@ static struct page *shmem_alloc_page(gfp_t gfp,
pvma.vm_ops = NULL;
pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
- /*
- * alloc_page_vma() will drop the shared policy reference
- */
- return alloc_page_vma(gfp, &pvma, 0);
+ page = alloc_page_vma(gfp, &pvma, 0);
+
+ /* Drop reference taken by mpol_shared_policy_lookup() */
+ mpol_cond_put(pvma.vm_policy);
+
+ return page;
}
#else /* !CONFIG_NUMA */
#ifdef CONFIG_TMPFS
diff --git a/mm/sparse.c b/mm/sparse.c
index fac95f2888f2..a83de2f72b30 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -617,7 +617,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
{
return; /* XXX: Not implemented yet */
}
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
{
}
#else
@@ -658,10 +658,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
get_order(sizeof(struct page) * nr_pages));
}
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
{
unsigned long maps_section_nr, removing_section_nr, i;
unsigned long magic;
+ struct page *page = virt_to_page(memmap);
for (i = 0; i < nr_pages; i++, page++) {
magic = (unsigned long) page->lru.next;
@@ -710,13 +711,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
*/
if (memmap) {
- struct page *memmap_page;
- memmap_page = virt_to_page(memmap);
-
nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
>> PAGE_SHIFT;
- free_map_bootmem(memmap_page, nr_pages);
+ free_map_bootmem(memmap, nr_pages);
}
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 48550c66f1f2..b7ed37675644 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2207,9 +2207,12 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
* Throttle direct reclaimers if backing storage is backed by the network
* and the PFMEMALLOC reserve for the preferred node is getting dangerously
* depleted. kswapd will continue to make progress and wake the processes
- * when the low watermark is reached
+ * when the low watermark is reached.
+ *
+ * Returns true if a fatal signal was delivered during throttling. If this
+ * happens, the page allocator should not consider triggering the OOM killer.
*/
-static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
+static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
nodemask_t *nodemask)
{
struct zone *zone;
@@ -2224,13 +2227,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
* processes to block on log_wait_commit().
*/
if (current->flags & PF_KTHREAD)
- return;
+ goto out;
+
+ /*
+ * If a fatal signal is pending, this process should not throttle.
+ * It should return quickly so it can exit and free its memory
+ */
+ if (fatal_signal_pending(current))
+ goto out;
/* Check if the pfmemalloc reserves are ok */
first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone);
pgdat = zone->zone_pgdat;
if (pfmemalloc_watermark_ok(pgdat))
- return;
+ goto out;
/* Account for the throttling */
count_vm_event(PGSCAN_DIRECT_THROTTLE);
@@ -2246,12 +2256,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
if (!(gfp_mask & __GFP_FS)) {
wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
pfmemalloc_watermark_ok(pgdat), HZ);
- return;
+
+ goto check_pending;
}
/* Throttle until kswapd wakes the process */
wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
pfmemalloc_watermark_ok(pgdat));
+
+check_pending:
+ if (fatal_signal_pending(current))
+ return true;
+
+out:
+ return false;
}
unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
@@ -2273,13 +2291,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
.gfp_mask = sc.gfp_mask,
};
- throttle_direct_reclaim(gfp_mask, zonelist, nodemask);
-
/*
- * Do not enter reclaim if fatal signal is pending. 1 is returned so
- * that the page allocator does not consider triggering OOM
+ * Do not enter reclaim if fatal signal was delivered while throttled.
+ * 1 is returned so that the page allocator does not OOM kill at this
+ * point.
*/
- if (fatal_signal_pending(current))
+ if (throttle_direct_reclaim(gfp_mask, zonelist, nodemask))
return 1;
trace_mm_vmscan_direct_reclaim_begin(order,
@@ -2397,6 +2414,19 @@ static void age_active_anon(struct zone *zone, struct scan_control *sc)
} while (memcg);
}
+static bool zone_balanced(struct zone *zone, int order,
+ unsigned long balance_gap, int classzone_idx)
+{
+ if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) +
+ balance_gap, classzone_idx, 0))
+ return false;
+
+ if (COMPACTION_BUILD && order && !compaction_suitable(zone, order))
+ return false;
+
+ return true;
+}
+
/*
* pgdat_balanced is used when checking if a node is balanced for high-order
* allocations. Only zones that meet watermarks and are in a zone allowed
@@ -2475,8 +2505,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
continue;
}
- if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
- i, 0))
+ if (!zone_balanced(zone, order, 0, i))
all_zones_ok = false;
else
balanced += zone->present_pages;
@@ -2585,8 +2614,7 @@ loop_again:
break;
}
- if (!zone_watermark_ok_safe(zone, order,
- high_wmark_pages(zone), 0, 0)) {
+ if (!zone_balanced(zone, order, 0, 0)) {
end_zone = i;
break;
} else {
@@ -2662,9 +2690,8 @@ loop_again:
testorder = 0;
if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
- !zone_watermark_ok_safe(zone, testorder,
- high_wmark_pages(zone) + balance_gap,
- end_zone, 0)) {
+ !zone_balanced(zone, testorder,
+ balance_gap, end_zone)) {
shrink_zone(zone, &sc);
reclaim_state->reclaimed_slab = 0;
@@ -2691,8 +2718,7 @@ loop_again:
continue;
}
- if (!zone_watermark_ok_safe(zone, testorder,
- high_wmark_pages(zone), end_zone, 0)) {
+ if (!zone_balanced(zone, testorder, 0, end_zone)) {
all_zones_ok = 0;
/*
* We are still under min water mark. This
@@ -2797,29 +2823,10 @@ out:
if (!populated_zone(zone))
continue;
- if (zone->all_unreclaimable &&
- sc.priority != DEF_PRIORITY)
- continue;
-
- /* Would compaction fail due to lack of free memory? */
- if (COMPACTION_BUILD &&
- compaction_suitable(zone, order) == COMPACT_SKIPPED)
- goto loop_again;
-
- /* Confirm the zone is balanced for order-0 */
- if (!zone_watermark_ok(zone, 0,
- high_wmark_pages(zone), 0, 0)) {
- order = sc.order = 0;
- goto loop_again;
- }
-
/* Check if the memory needs to be defragmented. */
if (zone_watermark_ok(zone, order,
low_wmark_pages(zone), *classzone_idx, 0))
zones_need_compaction = 0;
-
- /* If balanced, clear the congested flag */
- zone_clear_flag(zone, ZONE_CONGESTED);
}
if (zones_need_compaction)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 6f747582718e..969b7cdff59d 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
op->sk = sk;
op->ifindex = ifindex;
+ /* ifindex for timeout events w/o previous frame reception */
+ op->rx_ifindex = ifindex;
+
/* initialize uninitialized (kzalloc) structure */
hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
op->timer.function = bcm_rx_timeout_handler;
diff --git a/net/core/dev.c b/net/core/dev.c
index c0946cb2b354..e5942bf45a6d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3451,6 +3451,8 @@ static int napi_gro_complete(struct sk_buff *skb)
struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
int err = -ENOENT;
+ BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));
+
if (NAPI_GRO_CB(skb)->count == 1) {
skb_shinfo(skb)->gso_size = 0;
goto out;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index bcf02f608cbf..017a8bacfb27 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -429,6 +429,17 @@ static struct attribute_group netstat_group = {
.name = "statistics",
.attrs = netstat_attrs,
};
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+static struct attribute *wireless_attrs[] = {
+ NULL
+};
+
+static struct attribute_group wireless_group = {
+ .name = "wireless",
+ .attrs = wireless_attrs,
+};
+#endif
#endif /* CONFIG_SYSFS */
#ifdef CONFIG_RPS
@@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net)
groups++;
*groups++ = &netstat_group;
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+ if (net->ieee80211_ptr)
+ *groups++ = &wireless_group;
+#if IS_ENABLED(CONFIG_WIRELESS_EXT)
+ else if (net->wireless_handlers)
+ *groups++ = &wireless_group;
+#endif
+#endif
#endif /* CONFIG_SYSFS */
error = device_add(dev);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 4007c1437fda..3f0636cd76cd 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3004,7 +3004,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
skb_shinfo(nskb)->gso_size = pinfo->gso_size;
pinfo->gso_size = 0;
skb_header_release(p);
- nskb->prev = p;
+ NAPI_GRO_CB(nskb)->last = p;
nskb->data_len += p->len;
nskb->truesize += p->truesize;
@@ -3030,8 +3030,8 @@ merge:
__skb_pull(skb, offset);
- p->prev->next = skb;
- p->prev = skb;
+ NAPI_GRO_CB(p)->last->next = skb;
+ NAPI_GRO_CB(p)->last = skb;
skb_header_release(skb);
done:
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index f2eccd531746..17ff9fd7cdda 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -257,7 +257,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1);
rc = inet_peer_xrlim_allow(peer,
net->ipv4.sysctl_icmp_ratelimit);
- inet_putpeer(peer);
+ if (peer)
+ inet_putpeer(peer);
}
out:
return rc;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 0c34bfabc11f..e23e16dc501d 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -44,6 +44,10 @@ struct inet_diag_entry {
u16 dport;
u16 family;
u16 userlocks;
+#if IS_ENABLED(CONFIG_IPV6)
+ struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */
+ struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */
+#endif
};
static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -428,25 +432,31 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
break;
}
- if (cond->prefix_len == 0)
- break;
-
if (op->code == INET_DIAG_BC_S_COND)
addr = entry->saddr;
else
addr = entry->daddr;
+ if (cond->family != AF_UNSPEC &&
+ cond->family != entry->family) {
+ if (entry->family == AF_INET6 &&
+ cond->family == AF_INET) {
+ if (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == htonl(0xffff) &&
+ bitstring_match(addr + 3,
+ cond->addr,
+ cond->prefix_len))
+ break;
+ }
+ yes = 0;
+ break;
+ }
+
+ if (cond->prefix_len == 0)
+ break;
if (bitstring_match(addr, cond->addr,
cond->prefix_len))
break;
- if (entry->family == AF_INET6 &&
- cond->family == AF_INET) {
- if (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == htonl(0xffff) &&
- bitstring_match(addr + 3, cond->addr,
- cond->prefix_len))
- break;
- }
yes = 0;
break;
}
@@ -509,6 +519,55 @@ static int valid_cc(const void *bc, int len, int cc)
return 0;
}
+/* Validate an inet_diag_hostcond. */
+static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
+ int *min_len)
+{
+ int addr_len;
+ struct inet_diag_hostcond *cond;
+
+ /* Check hostcond space. */
+ *min_len += sizeof(struct inet_diag_hostcond);
+ if (len < *min_len)
+ return false;
+ cond = (struct inet_diag_hostcond *)(op + 1);
+
+ /* Check address family and address length. */
+ switch (cond->family) {
+ case AF_UNSPEC:
+ addr_len = 0;
+ break;
+ case AF_INET:
+ addr_len = sizeof(struct in_addr);
+ break;
+ case AF_INET6:
+ addr_len = sizeof(struct in6_addr);
+ break;
+ default:
+ return false;
+ }
+ *min_len += addr_len;
+ if (len < *min_len)
+ return false;
+
+ /* Check prefix length (in bits) vs address length (in bytes). */
+ if (cond->prefix_len > 8 * addr_len)
+ return false;
+
+ return true;
+}
+
+/* Validate a port comparison operator. */
+static inline bool valid_port_comparison(const struct inet_diag_bc_op *op,
+ int len, int *min_len)
+{
+ /* Port comparisons put the port in a follow-on inet_diag_bc_op. */
+ *min_len += sizeof(struct inet_diag_bc_op);
+ if (len < *min_len)
+ return false;
+ return true;
+}
+
static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
{
const void *bc = bytecode;
@@ -516,29 +575,39 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
while (len > 0) {
const struct inet_diag_bc_op *op = bc;
+ int min_len = sizeof(struct inet_diag_bc_op);
//printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
switch (op->code) {
- case INET_DIAG_BC_AUTO:
case INET_DIAG_BC_S_COND:
case INET_DIAG_BC_D_COND:
+ if (!valid_hostcond(bc, len, &min_len))
+ return -EINVAL;
+ break;
case INET_DIAG_BC_S_GE:
case INET_DIAG_BC_S_LE:
case INET_DIAG_BC_D_GE:
case INET_DIAG_BC_D_LE:
- case INET_DIAG_BC_JMP:
- if (op->no < 4 || op->no > len + 4 || op->no & 3)
- return -EINVAL;
- if (op->no < len &&
- !valid_cc(bytecode, bytecode_len, len - op->no))
+ if (!valid_port_comparison(bc, len, &min_len))
return -EINVAL;
break;
+ case INET_DIAG_BC_AUTO:
+ case INET_DIAG_BC_JMP:
case INET_DIAG_BC_NOP:
break;
default:
return -EINVAL;
}
- if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
+
+ if (op->code != INET_DIAG_BC_NOP) {
+ if (op->no < min_len || op->no > len + 4 || op->no & 3)
+ return -EINVAL;
+ if (op->no < len &&
+ !valid_cc(bytecode, bytecode_len, len - op->no))
+ return -EINVAL;
+ }
+
+ if (op->yes < min_len || op->yes > len + 4 || op->yes & 3)
return -EINVAL;
bc += op->yes;
len -= op->yes;
@@ -596,6 +665,36 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
}
+/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
+ * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
+ */
+static inline void inet_diag_req_addrs(const struct sock *sk,
+ const struct request_sock *req,
+ struct inet_diag_entry *entry)
+{
+ struct inet_request_sock *ireq = inet_rsk(req);
+
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6) {
+ if (req->rsk_ops->family == AF_INET6) {
+ entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32;
+ entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32;
+ } else if (req->rsk_ops->family == AF_INET) {
+ ipv6_addr_set_v4mapped(ireq->loc_addr,
+ &entry->saddr_storage);
+ ipv6_addr_set_v4mapped(ireq->rmt_addr,
+ &entry->daddr_storage);
+ entry->saddr = entry->saddr_storage.s6_addr32;
+ entry->daddr = entry->daddr_storage.s6_addr32;
+ }
+ } else
+#endif
+ {
+ entry->saddr = &ireq->loc_addr;
+ entry->daddr = &ireq->rmt_addr;
+ }
+}
+
static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
struct request_sock *req,
struct user_namespace *user_ns,
@@ -637,8 +736,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
r->idiag_inode = 0;
#if IS_ENABLED(CONFIG_IPV6)
if (r->idiag_family == AF_INET6) {
- *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr;
- *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr;
+ struct inet_diag_entry entry;
+ inet_diag_req_addrs(sk, req, &entry);
+ memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
+ memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
}
#endif
@@ -691,18 +792,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
continue;
if (bc) {
- entry.saddr =
-#if IS_ENABLED(CONFIG_IPV6)
- (entry.family == AF_INET6) ?
- inet6_rsk(req)->loc_addr.s6_addr32 :
-#endif
- &ireq->loc_addr;
- entry.daddr =
-#if IS_ENABLED(CONFIG_IPV6)
- (entry.family == AF_INET6) ?
- inet6_rsk(req)->rmt_addr.s6_addr32 :
-#endif
- &ireq->rmt_addr;
+ inet_diag_req_addrs(sk, req, &entry);
entry.dport = ntohs(ireq->rmt_port);
if (!inet_diag_bc_run(bc, &entry))
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 448e68546827..8d5cc75dac88 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -707,28 +707,27 @@ EXPORT_SYMBOL(ip_defrag);
struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
{
- const struct iphdr *iph;
+ struct iphdr iph;
u32 len;
if (skb->protocol != htons(ETH_P_IP))
return skb;
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+ if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
return skb;
- iph = ip_hdr(skb);
- if (iph->ihl < 5 || iph->version != 4)
+ if (iph.ihl < 5 || iph.version != 4)
return skb;
- if (!pskb_may_pull(skb, iph->ihl*4))
- return skb;
- iph = ip_hdr(skb);
- len = ntohs(iph->tot_len);
- if (skb->len < len || len < (iph->ihl * 4))
+
+ len = ntohs(iph.tot_len);
+ if (skb->len < len || len < (iph.ihl * 4))
return skb;
- if (ip_is_fragment(ip_hdr(skb))) {
+ if (ip_is_fragment(&iph)) {
skb = skb_share_check(skb, GFP_ATOMIC);
if (skb) {
+ if (!pskb_may_pull(skb, iph.ihl*4))
+ return skb;
if (pskb_trim_rcsum(skb, len))
return skb;
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 6168c4dc58b1..3eab2b2ffd34 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1318,6 +1318,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
if (get_user(v, (u32 __user *)optval))
return -EFAULT;
+ /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
+ if (v != RT_TABLE_DEFAULT && v >= 1000000000)
+ return -EINVAL;
+
rtnl_lock();
ret = 0;
if (sk == rtnl_dereference(mrt->mroute_sk)) {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a8c651216fa6..df251424d816 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1785,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
if (dev_out->flags & IFF_LOOPBACK)
flags |= RTCF_LOCAL;
+ do_cache = true;
if (type == RTN_BROADCAST) {
flags |= RTCF_BROADCAST | RTCF_LOCAL;
fi = NULL;
@@ -1793,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
fl4->flowi4_proto))
flags &= ~RTCF_LOCAL;
+ else
+ do_cache = false;
/* If multicast route do not exist use
* default one, but do not gateway in this case.
* Yes, it is hack.
@@ -1802,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
}
fnhe = NULL;
- do_cache = fi != NULL;
- if (fi) {
+ do_cache &= fi != NULL;
+ if (do_cache) {
struct rtable __rcu **prth;
struct fib_nh *nh = &FIB_RES_NH(*res);
@@ -2597,7 +2600,7 @@ int __init ip_rt_init(void)
pr_err("Unable to create route proc files\n");
#ifdef CONFIG_XFRM
xfrm_init();
- xfrm4_init(ip_rt_max_size);
+ xfrm4_init();
#endif
rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 083092e3aed6..e457c7ab2e28 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -830,8 +830,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
return mss_now;
}
-static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
- size_t psize, int flags)
+static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+ size_t size, int flags)
{
struct tcp_sock *tp = tcp_sk(sk);
int mss_now, size_goal;
@@ -858,12 +858,9 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
goto out_err;
- while (psize > 0) {
+ while (size > 0) {
struct sk_buff *skb = tcp_write_queue_tail(sk);
- struct page *page = pages[poffset / PAGE_SIZE];
int copy, i;
- int offset = poffset % PAGE_SIZE;
- int size = min_t(size_t, psize, PAGE_SIZE - offset);
bool can_coalesce;
if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) {
@@ -912,8 +909,8 @@ new_segment:
TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
copied += copy;
- poffset += copy;
- if (!(psize -= copy))
+ offset += copy;
+ if (!(size -= copy))
goto out;
if (skb->len < size_goal || (flags & MSG_OOB))
@@ -960,7 +957,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset,
flags);
lock_sock(sk);
- res = do_tcp_sendpages(sk, &page, offset, size, flags);
+ res = do_tcp_sendpages(sk, page, offset, size, flags);
release_sock(sk);
return res;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 609ff98aeb47..181fc8234a52 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5645,7 +5645,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
if (data) { /* Retransmit unacked data in SYN */
- tcp_retransmit_skb(sk, data);
+ tcp_for_write_queue_from(data, sk) {
+ if (data == tcp_send_head(sk) ||
+ __tcp_retransmit_skb(sk, data))
+ break;
+ }
tcp_rearm_rto(sk);
return true;
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 2798706cb063..948ac275b9b5 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2309,12 +2309,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
* state updates are done by the caller. Returns non-zero if an
* error occurred which prevented the send.
*/
-int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
unsigned int cur_mss;
- int err;
/* Inconslusive MTU probe */
if (icsk->icsk_mtup.probe_size) {
@@ -2387,11 +2386,17 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
GFP_ATOMIC);
- err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
- -ENOBUFS;
+ return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
+ -ENOBUFS;
} else {
- err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+ return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
}
+}
+
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ int err = __tcp_retransmit_skb(sk, skb);
if (err == 0) {
/* Update global TCP statistics. */
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 05c5ab8d983c..3be0ac2c1920 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void)
xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
}
-void __init xfrm4_init(int rt_max_size)
+void __init xfrm4_init(void)
{
- /*
- * Select a default value for the gc_thresh based on the main route
- * table hash size. It seems to me the worst case scenario is when
- * we have ipsec operating in transport mode, in which we create a
- * dst_entry per socket. The xfrm gc algorithm starts trying to remove
- * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
- * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
- * That will let us store an ipsec connection per route table entry,
- * and start cleaning when were 1/2 full
- */
- xfrm4_dst_ops.gc_thresh = rt_max_size/2;
dst_entries_init(&xfrm4_dst_ops);
xfrm4_state_init();
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index c4f934176cab..30647857a375 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
return NULL;
dst->ops->update_pmtu(dst, sk, NULL, mtu);
- return inet6_csk_route_socket(sk, &fl6);
+ dst = inet6_csk_route_socket(sk, &fl6);
+ return IS_ERR(dst) ? NULL : dst;
}
EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 1002e3396f72..ae43c62f9045 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -441,6 +441,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
if (lsap == NULL) {
IRDA_DEBUG(0, "%s: unable to allocate LSAP!!\n", __func__);
+ __irttp_close_tsap(self);
return NULL;
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index bf87c70ac6c5..c21e33d1abd0 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
mutex_lock(&sdata->u.ibss.mtx);
- sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
- memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
- sdata->u.ibss.ssid_len = 0;
-
active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
}
}
+ ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
+ memset(ifibss->bssid, 0, ETH_ALEN);
+ ifibss->ssid_len = 0;
+
sta_info_flush(sdata->local, sdata);
spin_lock_bh(&ifibss->incomplete_lock);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 83608ac16780..2c84185dfdb0 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -458,8 +458,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
list_move_tail(&roc->list, &tmp_list);
roc->abort = true;
}
-
- ieee80211_start_next_roc(local);
mutex_unlock(&local->mtx);
list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index ec3dba5dcd62..5c0b78528e55 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
return adtfn(set, &nip, timeout, flags);
}
+ ip_to = ip;
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
@@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
if (!cidr || cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
+ }
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index 0171f7502fa5..6283351f4eeb 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem data = { };
- u32 ip, ip_to = 0, p = 0, port, port_to;
+ u32 ip, ip_to, p = 0, port, port_to;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
return ip_set_eexist(ret, flags) ? 0 : ret;
}
- ip = ntohl(data.ip);
+ ip_to = ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
@@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
if (!cidr || cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
+ }
port_to = port = ntohs(data.port);
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 6344ef551ec8..6a21271c8d5a 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem data = { };
- u32 ip, ip_to = 0, p = 0, port, port_to;
+ u32 ip, ip_to, p = 0, port, port_to;
u32 timeout = h->timeout;
bool with_ports = false;
int ret;
@@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
return ip_set_eexist(ret, flags) ? 0 : ret;
}
- ip = ntohl(data.ip);
+ ip_to = ip = ntohl(data.ip);
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
@@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
if (!cidr || cidr > 32)
return -IPSET_ERR_INVALID_CIDR;
ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
+ }
port_to = port = ntohs(data.port);
if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index cb71f9a774e7..2d5cd4ee30eb 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
- u32 ip, ip_to = 0, p = 0, port, port_to;
- u32 ip2_from = 0, ip2_to, ip2_last, ip2;
+ u32 ip, ip_to, p = 0, port, port_to;
+ u32 ip2_from, ip2_to, ip2_last, ip2;
u32 timeout = h->timeout;
bool with_ports = false;
u8 cidr;
@@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
return ip_set_eexist(ret, flags) ? 0 : ret;
}
+ ip_to = ip;
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
@@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
if (port > port_to)
swap(port, port_to);
}
+
+ ip2_to = ip2_from;
if (tb[IPSET_ATTR_IP2_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
if (ret)
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index b9a63381e349..45a101439bc5 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -793,7 +793,7 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
+ .len = IFNAMSIZ - 1 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 8847b4d8be06..701c88a20fea 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu
static LIST_HEAD(cttimeout_list);
static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
- [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING },
+ [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING,
+ .len = CTNL_TIMEOUT_NAME_MAX - 1},
[CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 },
[CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 },
[CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index cc10d073c338..9e8f4b2801f6 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
local->remote_miu = LLCP_DEFAULT_MIU;
local->remote_lto = LLCP_DEFAULT_LTO;
- list_add(&llcp_devices, &local->list);
+ list_add(&local->list, &llcp_devices);
return 0;
}
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 98c70630ad06..733cbf49ed1f 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -702,15 +702,11 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
/* We only match on the lower 8 bits of the opcode. */
if (ntohs(arp->ar_op) <= 0xff)
key->ip.proto = ntohs(arp->ar_op);
-
- if (key->ip.proto == ARPOP_REQUEST
- || key->ip.proto == ARPOP_REPLY) {
- memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
- memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
- memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
- memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
- key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
- }
+ memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
+ memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
+ memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+ memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
+ key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
}
} else if (key->eth.type == htons(ETH_P_IPV6)) {
int nh_len; /* IPv6 Header + Extensions */
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 3c1e58ba714b..a9033481fa5e 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -158,7 +158,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
- ovs_dp_name(vport->dp),
+ netdev_vport->dev->name,
packet_length(skb), mtu);
goto error;
}
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 7c2df9c33df3..69ce21e3716f 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
msg = sctp_datamsg_new(GFP_KERNEL);
if (!msg)
- return NULL;
+ return ERR_PTR(-ENOMEM);
/* Note: Calculate this outside of the loop, so that all fragments
* have the same expiration.
@@ -280,11 +280,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
- if (!chunk)
+ if (!chunk) {
+ err = -ENOMEM;
goto errout;
+ }
+
err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
if (err < 0)
- goto errout;
+ goto errout_chunk_free;
offset += len;
@@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
- if (!chunk)
+ if (!chunk) {
+ err = -ENOMEM;
goto errout;
+ }
err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
@@ -324,7 +329,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
- (__u8 *)chunk->skb->data);
if (err < 0)
- goto errout;
+ goto errout_chunk_free;
sctp_datamsg_assign(msg, chunk);
list_add_tail(&chunk->frag_list, &msg->chunks);
@@ -332,6 +337,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
return msg;
+errout_chunk_free:
+ sctp_chunk_free(chunk);
+
errout:
list_for_each_safe(pos, temp, &msg->chunks) {
list_del_init(pos);
@@ -339,7 +347,7 @@ errout:
sctp_chunk_free(chunk);
}
sctp_datamsg_put(msg);
- return NULL;
+ return ERR_PTR(err);
}
/* Check whether this message has expired. */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a60d1f8b41c5..406d957d08fb 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1915,8 +1915,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
/* Break the message into multiple chunks of maximum size. */
datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
- if (!datamsg) {
- err = -ENOMEM;
+ if (IS_ERR(datamsg)) {
+ err = PTR_ERR(datamsg);
goto out_free;
}
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 953c21e4af97..206cf5238fd3 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -331,7 +331,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
* 1/8, rto_alpha would be expressed as 3.
*/
tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
- + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta);
+ + (((__u32)abs64((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta);
tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
+ (rtt >> net->sctp.rto_alpha);
} else {
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0be6f110cce7..bdf42fdf64c9 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -266,6 +266,9 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
quiet_cmd_dtc = DTC $@
cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $<
+$(obj)/%.dtb: $(src)/%.dts FORCE
+ $(call if_changed_dep,dtc)
+
# Bzip2
# ---------------------------------------------------------------------------
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 6d1c6bb9f224..2a48022c41e7 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -27,3 +27,5 @@ HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
+# generated files need to be cleaned explicitly
+clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
index 239d22d4207b..6c353ae8a451 100644
--- a/scripts/headers_install.pl
+++ b/scripts/headers_install.pl
@@ -42,6 +42,9 @@ foreach my $filename (@files) {
$line =~ s/(^|\s)(inline)\b/$1__$2__/g;
$line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
$line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
+ $line =~ s/#ifndef _UAPI/#ifndef /;
+ $line =~ s/#define _UAPI/#define /;
+ $line =~ s!#endif /[*] _UAPI!#endif /* !;
printf {$out} "%s", $line;
}
close $out;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0d93856a03f4..ff36c508a10e 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -858,25 +858,23 @@ static void check_section(const char *modname, struct elf_info *elf,
#define ALL_INIT_DATA_SECTIONS \
".init.setup$", ".init.rodata$", \
- ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \
- ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
+ ".cpuinit.rodata$", ".meminit.rodata$", \
+ ".init.data$", ".cpuinit.data$", ".meminit.data$"
#define ALL_EXIT_DATA_SECTIONS \
- ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
+ ".exit.data$", ".cpuexit.data$", ".memexit.data$"
#define ALL_INIT_TEXT_SECTIONS \
- ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$"
+ ".init.text$", ".cpuinit.text$", ".meminit.text$"
#define ALL_EXIT_TEXT_SECTIONS \
- ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"
+ ".exit.text$", ".cpuexit.text$", ".memexit.text$"
#define ALL_PCI_INIT_SECTIONS \
".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \
".pci_fixup_enable$", ".pci_fixup_resume$", \
".pci_fixup_resume_early$", ".pci_fixup_suspend$"
-#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \
- MEM_INIT_SECTIONS
-#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \
- MEM_EXIT_SECTIONS
+#define ALL_XXXINIT_SECTIONS CPU_INIT_SECTIONS, MEM_INIT_SECTIONS
+#define ALL_XXXEXIT_SECTIONS CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS
#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
@@ -885,12 +883,10 @@ static void check_section(const char *modname, struct elf_info *elf,
#define TEXT_SECTIONS ".text$"
#define INIT_SECTIONS ".init.*"
-#define DEV_INIT_SECTIONS ".devinit.*"
#define CPU_INIT_SECTIONS ".cpuinit.*"
#define MEM_INIT_SECTIONS ".meminit.*"
#define EXIT_SECTIONS ".exit.*"
-#define DEV_EXIT_SECTIONS ".devexit.*"
#define CPU_EXIT_SECTIONS ".cpuexit.*"
#define MEM_EXIT_SECTIONS ".memexit.*"
@@ -979,7 +975,7 @@ const struct sectioncheck sectioncheck[] = {
.mismatch = DATA_TO_ANY_EXIT,
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
-/* Do not reference init code/data from devinit/cpuinit/meminit code/data */
+/* Do not reference init code/data from cpuinit/meminit code/data */
{
.fromsec = { ALL_XXXINIT_SECTIONS, NULL },
.tosec = { INIT_SECTIONS, NULL },
@@ -1000,7 +996,7 @@ const struct sectioncheck sectioncheck[] = {
.mismatch = XXXINIT_TO_SOME_INIT,
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
},
-/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */
+/* Do not reference exit code/data from cpuexit/memexit code/data */
{
.fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
.tosec = { EXIT_SECTIONS, NULL },
@@ -1089,7 +1085,7 @@ static const struct sectioncheck *section_mismatch(
* Pattern 2:
* Many drivers utilise a *driver container with references to
* add, remove, probe functions etc.
- * These functions may often be marked __devinit and we do not want to
+ * These functions may often be marked __cpuinit and we do not want to
* warn here.
* the pattern is identified by:
* tosec = init or exit section
diff --git a/scripts/sign-file b/scripts/sign-file
index 87ca59d36e7e..974a20b661b7 100755
--- a/scripts/sign-file
+++ b/scripts/sign-file
@@ -156,12 +156,12 @@ sub asn1_extract($$@)
if ($l == 0x1) {
$len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
- } elsif ($l = 0x2) {
+ } elsif ($l == 0x2) {
$len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
- } elsif ($l = 0x3) {
+ } elsif ($l == 0x3) {
$len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
$len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
- } elsif ($l = 0x4) {
+ } elsif ($l == 0x4) {
$len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
} else {
die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 28f911cdd7c7..c5454c0477c3 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
struct sel_netnode *tail;
tail = list_entry(
- rcu_dereference(sel_netnode_hash[idx].list.prev),
+ rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+ lockdep_is_held(&sel_netnode_lock)),
struct sel_netnode, list);
list_del_rcu(&tail->list);
kfree_rcu(tail, rcu);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 70d4848b5cd0..d010de12335e 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
#ifdef CONFIG_PM
+#define codec_in_pm(codec) ((codec)->in_pm)
static void hda_power_work(struct work_struct *work);
static void hda_keep_power_on(struct hda_codec *codec);
#define hda_codec_is_power_on(codec) ((codec)->power_on)
@@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
bus->ops.pm_notify(bus, power_up);
}
#else
+#define codec_in_pm(codec) 0
static inline void hda_keep_power_on(struct hda_codec *codec) {}
#define hda_codec_is_power_on(codec) 1
#define hda_call_pm_notify(bus, state) {}
@@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
}
mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
- if (res && *res == -1 && bus->rirb_error) {
+ if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
if (bus->response_reset) {
snd_printd("hda_codec: resetting BUS due to "
"fatal communication error\n");
@@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
goto again;
}
/* clear reset-flag when the communication gets recovered */
- if (!err)
+ if (!err || codec_in_pm(codec))
bus->response_reset = 0;
return err;
}
@@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
{
unsigned int state;
+ codec->in_pm = 1;
+
if (codec->patch_ops.suspend)
codec->patch_ops.suspend(codec);
hda_cleanup_all_streams(codec);
@@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
codec->power_transition = 0;
codec->power_jiffies = jiffies;
spin_unlock(&codec->power_lock);
+ codec->in_pm = 0;
return state;
}
@@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
*/
static void hda_call_codec_resume(struct hda_codec *codec)
{
+ codec->in_pm = 1;
+
/* set as if powered on for avoiding re-entering the resume
* in the resume / power-save sequence
*/
@@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
snd_hda_codec_resume_cache(codec);
}
snd_hda_jack_report_sync(codec);
+
+ codec->in_pm = 0;
snd_hda_power_down(codec); /* flag down before returning */
}
#endif /* CONFIG_PM */
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 507fe8a917b6..4f4e545c0f4b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -869,6 +869,7 @@ struct hda_codec {
unsigned int power_on :1; /* current (global) power-state */
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
unsigned int pm_down_notified:1; /* PM notified to controller */
+ unsigned int in_pm:1; /* suspend/resume being performed */
int power_transition; /* power-state in transition */
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cd2dbaf1be78..f9d870e554d9 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -556,6 +556,12 @@ enum {
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
+#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
+
+/* quirks for Intel PCH */
+#define AZX_DCAPS_INTEL_PCH \
+ (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
+ AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -2433,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
{
struct azx *chip = bus->private_data;
+ if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+ return;
+
if (power_up)
pm_runtime_get_sync(&chip->pci->dev);
else
@@ -2548,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
- if (!power_save_controller)
+ if (!power_save_controller ||
+ !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
return -EAGAIN;
azx_stop_chip(chip);
@@ -3429,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE},
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point */
{ PCI_DEVICE(0x8086, 0x8c20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Lynx Point-LP */
{ PCI_DEVICE(0x8086, 0x9c21),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
/* Haswell */
{ PCI_DEVICE(0x8086, 0x0c0c),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
{ PCI_DEVICE(0x8086, 0x0d0c),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
/* 5 Series/3400 */
{ PCI_DEVICE(0x8086, 0x3b56),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
- AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index d5f3a26d608d..3bcb67172358 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
memcpy(cfg->speaker_pins, cfg->line_out_pins,
sizeof(cfg->speaker_pins));
cfg->line_outs = 0;
+ memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
}
return 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 68fd49294b26..ad68d223f8af 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7065,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
+ { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index c03b65af3059..054967d8bac2 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
static unsigned int arizona_sysclk_48k_rates[] = {
6144000,
12288000,
- 22579200,
+ 24576000,
49152000,
73728000,
98304000,
@@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
static unsigned int arizona_sysclk_44k1_rates[] = {
5644800,
11289600,
- 24576000,
+ 22579200,
45158400,
67737600,
90316800,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index f994af34f552..e3f0a7f3131e 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
gpio_nreset = cs4271plat->gpio_nreset;
if (gpio_nreset >= 0)
- if (gpio_request(gpio_nreset, "CS4271 Reset"))
+ if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
gpio_nreset = -EINVAL;
if (gpio_nreset >= 0) {
/* Reset codec */
@@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
static int cs4271_remove(struct snd_soc_codec *codec)
{
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
- int gpio_nreset;
- gpio_nreset = cs4271->gpio_nreset;
-
- if (gpio_is_valid(gpio_nreset)) {
+ if (gpio_is_valid(cs4271->gpio_nreset))
/* Set codec to the reset state */
- gpio_set_value(gpio_nreset, 0);
- gpio_free(gpio_nreset);
- }
+ gpio_set_value(cs4271->gpio_nreset, 0);
return 0;
};
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index b9f16598324c..2ba08148655f 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
__func__, cause);
writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
- return IRQ_HANDLED;
}
/* we've enabled only bytes interrupts ... */
@@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
}
dram = mv_mbus_dram_info();
- addr = virt_to_phys(substream->dma_buffer.area);
+ addr = substream->dma_buffer.addr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
prdata->play_stream = substream;
kirkwood_dma_conf_mbus_windows(priv->io,
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 542538d10ab7..1d5db484d2df 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
do {
cpu_relax();
value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
- value &= KIRKWOOD_DCO_SPCR_STATUS;
+ value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
} while (value == 0);
}
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
- unsigned long value;
-
- /*
- * specs says KIRKWOOD_PLAYCTL must be read 2 times before
- * changing it. So read 1 time here and 1 later.
- */
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
+ uint32_t ctl, value;
+
+ ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+ if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+ unsigned timeout = 5000;
+ /*
+ * The Armada510 spec says that if we enter pause mode, the
+ * busy bit must be read back as clear _twice_. Make sure
+ * we respect that otherwise we get DMA underruns.
+ */
+ do {
+ value = ctl;
+ ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+ if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
+ break;
+ udelay(1);
+ } while (timeout--);
+
+ if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
+ dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
+ ctl);
+ }
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- /* stop audio, enable interrupts */
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value |= KIRKWOOD_PLAYCTL_PAUSE;
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
-
value = readl(priv->io + KIRKWOOD_INT_MASK);
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
/* configure audio & enable i2s playback */
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
- value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
+ ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
+ ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
| KIRKWOOD_PLAYCTL_SPDIF_EN);
if (priv->burst == 32)
- value |= KIRKWOOD_PLAYCTL_BURST_32;
+ ctl |= KIRKWOOD_PLAYCTL_BURST_32;
else
- value |= KIRKWOOD_PLAYCTL_BURST_128;
- value |= KIRKWOOD_PLAYCTL_I2S_EN;
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
+ ctl |= KIRKWOOD_PLAYCTL_BURST_128;
+ ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+ writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break;
case SNDRV_PCM_TRIGGER_STOP:
/* stop audio, disable interrupts */
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
+ ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+ writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
value = readl(priv->io + KIRKWOOD_INT_MASK);
value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
/* disable all playbacks */
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
+ ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+ writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
+ ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+ writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break;
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- value = readl(priv->io + KIRKWOOD_PLAYCTL);
- value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
- writel(value, priv->io + KIRKWOOD_PLAYCTL);
+ ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+ writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
break;
default:
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- /* stop audio, enable interrupts */
- value = readl(priv->io + KIRKWOOD_RECCTL);
- value |= KIRKWOOD_RECCTL_PAUSE;
- writel(value, priv->io + KIRKWOOD_RECCTL);
-
value = readl(priv->io + KIRKWOOD_INT_MASK);
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
writel(value, priv->io + KIRKWOOD_INT_MASK);
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index b56b9a3c6169..a2ca1567b9e4 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -212,7 +212,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
{
.name = "Sub",
.stream_name = "Sub",
- .cpu_dai_name = "wm5110-aif3",
+ .cpu_dai_name = "wm5102-aif3",
.codec_dai_name = "wm9081-hifi",
.codec_name = "wm9081.1-006c",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = {
{
.name = "Sub",
.stream_name = "Sub",
- .cpu_dai_name = "wm5102-aif3",
+ .cpu_dai_name = "wm5110-aif3",
.codec_dai_name = "wm9081-hifi",
.codec_name = "wm9081.1-006c",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index c83f6143c0eb..eeefbce3873c 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
struct snd_usb_midi_out_endpoint* ep;
struct snd_rawmidi_substream *substream;
int active;
+ bool autopm_reference;
uint8_t cable; /* cable number << 4 */
uint8_t state;
#define STATE_UNKNOWN 0
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
return -ENXIO;
}
err = usb_autopm_get_interface(umidi->iface);
- if (err < 0)
+ port->autopm_reference = err >= 0;
+ if (err < 0 && err != -EACCES)
return -EIO;
substream->runtime->private_data = port;
port->state = STATE_UNKNOWN;
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
{
struct snd_usb_midi* umidi = substream->rmidi->private_data;
+ struct usbmidi_out_port *port = substream->runtime->private_data;
substream_open(substream, 0);
- usb_autopm_put_interface(umidi->iface);
+ if (port->autopm_reference)
+ usb_autopm_put_interface(umidi->iface);
return 0;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 5c12a3fe8c3e..ef6fa24fc473 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -459,7 +459,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
return ret;
if (subs->sync_endpoint)
- ret = snd_usb_endpoint_set_params(subs->data_endpoint,
+ ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
subs->pcm_format,
subs->channels,
subs->period_bytes,
diff --git a/tools/Makefile b/tools/Makefile
index 3ae43947a171..1f9a529fe544 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -31,44 +31,44 @@ help:
@echo ' clean: a summary clean target to clean _all_ folders'
cpupower: FORCE
- $(QUIET_SUBDIR0)power/$@/ $(QUIET_SUBDIR1)
+ $(call descend,power/$@)
firewire lguest perf usb virtio vm: FORCE
- $(QUIET_SUBDIR0)$@/ $(QUIET_SUBDIR1)
+ $(call descend,$@)
selftests: FORCE
- $(QUIET_SUBDIR0)testing/$@/ $(QUIET_SUBDIR1)
+ $(call descend,testing/$@)
turbostat x86_energy_perf_policy: FORCE
- $(QUIET_SUBDIR0)power/x86/$@/ $(QUIET_SUBDIR1)
+ $(call descend,power/x86/$@)
cpupower_install:
- $(QUIET_SUBDIR0)power/$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,power/$(@:_install=),install)
firewire_install lguest_install perf_install usb_install virtio_install vm_install:
- $(QUIET_SUBDIR0)$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,$(@:_install=),install)
selftests_install:
- $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) install
+ $(call descend,testing/$(@:_clean=),install)
turbostat_install x86_energy_perf_policy_install:
- $(QUIET_SUBDIR0)power/x86/$(@:_install=)/ $(QUIET_SUBDIR1) install
+ $(call descend,power/x86/$(@:_install=),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
+ $(call descend,power/cpupower,clean)
firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean:
- $(QUIET_SUBDIR0)$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,$(@:_clean=),clean)
selftests_clean:
- $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,testing/$(@:_clean=),clean)
turbostat_clean x86_energy_perf_policy_clean:
- $(QUIET_SUBDIR0)power/x86/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+ $(call descend,power/x86/$(@:_clean=),clean)
clean: cpupower_clean firewire_clean lguest_clean perf_clean selftests_clean \
turbostat_clean usb_clean virtio_clean vm_clean \
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 5959affd8820..d25a46925e61 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -43,6 +43,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
+#include <net/if.h>
/*
* KVP protocol: The user mode component first registers with the
@@ -88,6 +89,7 @@ static char *os_major = "";
static char *os_minor = "";
static char *processor_arch;
static char *os_build;
+static char *os_version;
static char *lic_version = "Unknown version";
static struct utsname uts_buf;
@@ -297,7 +299,7 @@ static int kvp_file_init(void)
return 0;
}
-static int kvp_key_delete(int pool, __u8 *key, int key_size)
+static int kvp_key_delete(int pool, const char *key, int key_size)
{
int i;
int j, k;
@@ -340,7 +342,7 @@ static int kvp_key_delete(int pool, __u8 *key, int key_size)
return 1;
}
-static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
+static int kvp_key_add_or_modify(int pool, const char *key, int key_size, const char *value,
int value_size)
{
int i;
@@ -394,7 +396,7 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
return 0;
}
-static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
+static int kvp_get_value(int pool, const char *key, int key_size, char *value,
int value_size)
{
int i;
@@ -426,8 +428,8 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
return 1;
}
-static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
- __u8 *value, int value_size)
+static int kvp_pool_enumerate(int pool, int index, char *key, int key_size,
+ char *value, int value_size)
{
struct kvp_record *record;
@@ -453,7 +455,9 @@ void kvp_get_os_info(void)
char *p, buf[512];
uname(&uts_buf);
- os_build = uts_buf.release;
+ os_version = uts_buf.release;
+ os_build = strdup(uts_buf.release);
+
os_name = uts_buf.sysname;
processor_arch = uts_buf.machine;
@@ -462,7 +466,7 @@ void kvp_get_os_info(void)
* string to be of the form: x.y.z
* Strip additional information we may have.
*/
- p = strchr(os_build, '-');
+ p = strchr(os_version, '-');
if (p)
*p = '\0';
@@ -879,7 +883,7 @@ static int kvp_process_ip_address(void *addrp,
addr_length = INET6_ADDRSTRLEN;
}
- if ((length - *offset) < addr_length + 1)
+ if ((length - *offset) < addr_length + 2)
return HV_E_FAIL;
if (str == NULL) {
strcpy(buffer, "inet_ntop failed\n");
@@ -887,11 +891,13 @@ static int kvp_process_ip_address(void *addrp,
}
if (*offset == 0)
strcpy(buffer, tmp);
- else
+ else {
+ strcat(buffer, ";");
strcat(buffer, tmp);
- strcat(buffer, ";");
+ }
*offset += strlen(str) + 1;
+
return 0;
}
@@ -953,7 +959,9 @@ kvp_get_ip_info(int family, char *if_name, int op,
* supported address families; if not we gather info on
* the specified address family.
*/
- if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
+ if ((((family != 0) &&
+ (curp->ifa_addr->sa_family != family))) ||
+ (curp->ifa_flags & IFF_LOOPBACK)) {
curp = curp->ifa_next;
continue;
}
@@ -1478,13 +1486,19 @@ int main(void)
len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0,
addr_p, &addr_l);
- if (len < 0 || addr.nl_pid) {
+ if (len < 0) {
syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
addr.nl_pid, errno, strerror(errno));
close(fd);
return -1;
}
+ if (addr.nl_pid) {
+ syslog(LOG_WARNING, "Received packet from untrusted pid:%u",
+ addr.nl_pid);
+ continue;
+ }
+
incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
@@ -1649,7 +1663,7 @@ int main(void)
strcpy(key_name, "OSMinorVersion");
break;
case OSVersion:
- strcpy(key_value, os_build);
+ strcpy(key_value, os_version);
strcpy(key_name, "OSVersion");
break;
case ProcessorArchitecture:
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 00deed4d6159..0a619af5be43 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -169,7 +169,34 @@ endif
### --- END CONFIGURATION SECTION ---
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+endif
+
+BASIC_CFLAGS = \
+ -Iutil/include \
+ -Iarch/$(ARCH)/include \
+ $(if $(objtree),-I$(objtree)/arch/$(ARCH)/include/generated/uapi) \
+ -I$(srctree)/arch/$(ARCH)/include/uapi \
+ -I$(srctree)/arch/$(ARCH)/include \
+ $(if $(objtree),-I$(objtree)/include/generated/uapi) \
+ -I$(srctree)/include/uapi \
+ -I$(srctree)/include \
+ -I$(OUTPUT)util \
+ -Iutil \
+ -I. \
+ -I$(TRACE_EVENT_DIR) \
+ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
# Guard against environment variables
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 46fc9f15c6b3..7fcdcdbee917 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include "../../util/types.h"
-#include "../../../../../arch/x86/include/asm/perf_regs.h"
+#include <asm/perf_regs.h>
#ifndef ARCH_X86_64
#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 260abc535b5b..283b4397e397 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -22,9 +22,10 @@
#include <pthread.h>
#include <math.h>
-#include "../../arch/x86/include/asm/svm.h"
-#include "../../arch/x86/include/asm/vmx.h"
-#include "../../arch/x86/include/asm/kvm.h"
+#if defined(__i386__) || defined(__x86_64__)
+#include <asm/svm.h>
+#include <asm/vmx.h>
+#include <asm/kvm.h>
struct event_key {
#define INVALID_KEY (~0ULL)
@@ -58,7 +59,7 @@ struct kvm_event_key {
};
-struct perf_kvm;
+struct perf_kvm_stat;
struct kvm_events_ops {
bool (*is_begin_event)(struct perf_evsel *evsel,
@@ -66,7 +67,7 @@ struct kvm_events_ops {
struct event_key *key);
bool (*is_end_event)(struct perf_evsel *evsel,
struct perf_sample *sample, struct event_key *key);
- void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
+ void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
char decode[20]);
const char *name;
};
@@ -79,7 +80,7 @@ struct exit_reasons_table {
#define EVENTS_BITS 12
#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
-struct perf_kvm {
+struct perf_kvm_stat {
struct perf_tool tool;
struct perf_session *session;
@@ -146,7 +147,7 @@ static struct exit_reasons_table svm_exit_reasons[] = {
SVM_EXIT_REASONS
};
-static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
+static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
{
int i = kvm->exit_reasons_size;
struct exit_reasons_table *tbl = kvm->exit_reasons;
@@ -162,7 +163,7 @@ static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
return "UNKNOWN";
}
-static void exit_event_decode_key(struct perf_kvm *kvm,
+static void exit_event_decode_key(struct perf_kvm_stat *kvm,
struct event_key *key,
char decode[20])
{
@@ -228,7 +229,7 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
return false;
}
-static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key,
char decode[20])
{
@@ -271,7 +272,7 @@ static bool ioport_event_end(struct perf_evsel *evsel,
return kvm_entry_event(evsel);
}
-static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key,
char decode[20])
{
@@ -286,7 +287,7 @@ static struct kvm_events_ops ioport_events = {
.name = "IO Port Access"
};
-static bool register_kvm_events_ops(struct perf_kvm *kvm)
+static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
{
bool ret = true;
@@ -311,7 +312,7 @@ struct vcpu_event_record {
};
-static void init_kvm_event_record(struct perf_kvm *kvm)
+static void init_kvm_event_record(struct perf_kvm_stat *kvm)
{
int i;
@@ -360,7 +361,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
return event;
}
-static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
+static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
struct event_key *key)
{
struct kvm_event *event;
@@ -381,7 +382,7 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
return event;
}
-static bool handle_begin_event(struct perf_kvm *kvm,
+static bool handle_begin_event(struct perf_kvm_stat *kvm,
struct vcpu_event_record *vcpu_record,
struct event_key *key, u64 timestamp)
{
@@ -425,7 +426,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
return true;
}
-static bool handle_end_event(struct perf_kvm *kvm,
+static bool handle_end_event(struct perf_kvm_stat *kvm,
struct vcpu_event_record *vcpu_record,
struct event_key *key,
u64 timestamp)
@@ -486,7 +487,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
return thread->priv;
}
-static bool handle_kvm_event(struct perf_kvm *kvm,
+static bool handle_kvm_event(struct perf_kvm_stat *kvm,
struct thread *thread,
struct perf_evsel *evsel,
struct perf_sample *sample)
@@ -541,7 +542,7 @@ static struct kvm_event_key keys[] = {
{ NULL, NULL }
};
-static bool select_key(struct perf_kvm *kvm)
+static bool select_key(struct perf_kvm_stat *kvm)
{
int i;
@@ -577,7 +578,8 @@ static void insert_to_result(struct rb_root *result, struct kvm_event *event,
rb_insert_color(&event->rb, result);
}
-static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
+static void
+update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event)
{
int vcpu = kvm->trace_vcpu;
@@ -590,7 +592,7 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
return !!get_event_count(event, vcpu);
}
-static void sort_result(struct perf_kvm *kvm)
+static void sort_result(struct perf_kvm_stat *kvm)
{
unsigned int i;
int vcpu = kvm->trace_vcpu;
@@ -627,7 +629,7 @@ static void print_vcpu_info(int vcpu)
pr_info("VCPU %d:\n\n", vcpu);
}
-static void print_result(struct perf_kvm *kvm)
+static void print_result(struct perf_kvm_stat *kvm)
{
char decode[20];
struct kvm_event *event;
@@ -670,7 +672,8 @@ static int process_sample_event(struct perf_tool *tool,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, sample->tid);
- struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
+ struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
+ tool);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
@@ -701,7 +704,7 @@ static int get_cpu_isa(struct perf_session *session)
return isa;
}
-static int read_events(struct perf_kvm *kvm)
+static int read_events(struct perf_kvm_stat *kvm)
{
int ret;
@@ -750,7 +753,7 @@ static bool verify_vcpu(int vcpu)
return true;
}
-static int kvm_events_report_vcpu(struct perf_kvm *kvm)
+static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
{
int ret = -EINVAL;
int vcpu = kvm->trace_vcpu;
@@ -798,7 +801,8 @@ static const char * const record_args[] = {
_p; \
})
-static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
{
unsigned int rec_argc, i, j;
const char **rec_argv;
@@ -821,7 +825,8 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
return cmd_record(i, rec_argv, NULL);
}
-static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
{
const struct option kvm_events_report_options[] = {
OPT_STRING(0, "event", &kvm->report_event, "report event",
@@ -864,24 +869,37 @@ static void print_kvm_stat_usage(void)
printf("\nOtherwise, it is the alias of 'perf stat':\n");
}
-static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
+static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
{
+ struct perf_kvm_stat kvm = {
+ .file_name = file_name,
+
+ .trace_vcpu = -1,
+ .report_event = "vmexit",
+ .sort_key = "sample",
+
+ .exit_reasons = svm_exit_reasons,
+ .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
+ .exit_reasons_isa = "SVM",
+ };
+
if (argc == 1) {
print_kvm_stat_usage();
goto perf_stat;
}
if (!strncmp(argv[1], "rec", 3))
- return kvm_events_record(kvm, argc - 1, argv + 1);
+ return kvm_events_record(&kvm, argc - 1, argv + 1);
if (!strncmp(argv[1], "rep", 3))
- return kvm_events_report(kvm, argc - 1 , argv + 1);
+ return kvm_events_report(&kvm, argc - 1 , argv + 1);
perf_stat:
return cmd_stat(argc, argv, NULL);
}
+#endif
-static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
+static int __cmd_record(const char *file_name, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -890,7 +908,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("record");
rec_argv[i++] = strdup("-o");
- rec_argv[i++] = strdup(kvm->file_name);
+ rec_argv[i++] = strdup(file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];
@@ -899,7 +917,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
return cmd_record(i, rec_argv, NULL);
}
-static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
+static int __cmd_report(const char *file_name, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -908,7 +926,7 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("report");
rec_argv[i++] = strdup("-i");
- rec_argv[i++] = strdup(kvm->file_name);
+ rec_argv[i++] = strdup(file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];
@@ -917,7 +935,8 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
return cmd_report(i, rec_argv, NULL);
}
-static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+__cmd_buildid_list(const char *file_name, int argc, const char **argv)
{
int rec_argc, i = 0, j;
const char **rec_argv;
@@ -926,7 +945,7 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
rec_argv = calloc(rec_argc + 1, sizeof(char *));
rec_argv[i++] = strdup("buildid-list");
rec_argv[i++] = strdup("-i");
- rec_argv[i++] = strdup(kvm->file_name);
+ rec_argv[i++] = strdup(file_name);
for (j = 1; j < argc; j++, i++)
rec_argv[i] = argv[j];
@@ -937,20 +956,12 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
{
- struct perf_kvm kvm = {
- .trace_vcpu = -1,
- .report_event = "vmexit",
- .sort_key = "sample",
-
- .exit_reasons = svm_exit_reasons,
- .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
- .exit_reasons_isa = "SVM",
- };
+ const char *file_name;
const struct option kvm_options[] = {
- OPT_STRING('i', "input", &kvm.file_name, "file",
+ OPT_STRING('i', "input", &file_name, "file",
"Input file name"),
- OPT_STRING('o', "output", &kvm.file_name, "file",
+ OPT_STRING('o', "output", &file_name, "file",
"Output file name"),
OPT_BOOLEAN(0, "guest", &perf_guest,
"Collect guest os data"),
@@ -985,32 +996,34 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
if (!perf_host)
perf_guest = 1;
- if (!kvm.file_name) {
+ if (!file_name) {
if (perf_host && !perf_guest)
- kvm.file_name = strdup("perf.data.host");
+ file_name = strdup("perf.data.host");
else if (!perf_host && perf_guest)
- kvm.file_name = strdup("perf.data.guest");
+ file_name = strdup("perf.data.guest");
else
- kvm.file_name = strdup("perf.data.kvm");
+ file_name = strdup("perf.data.kvm");
- if (!kvm.file_name) {
+ if (!file_name) {
pr_err("Failed to allocate memory for filename\n");
return -ENOMEM;
}
}
if (!strncmp(argv[0], "rec", 3))
- return __cmd_record(&kvm, argc, argv);
+ return __cmd_record(file_name, argc, argv);
else if (!strncmp(argv[0], "rep", 3))
- return __cmd_report(&kvm, argc, argv);
+ return __cmd_report(file_name, argc, argv);
else if (!strncmp(argv[0], "diff", 4))
return cmd_diff(argc, argv, NULL);
else if (!strncmp(argv[0], "top", 3))
return cmd_top(argc, argv, NULL);
else if (!strncmp(argv[0], "buildid-list", 12))
- return __cmd_buildid_list(&kvm, argc, argv);
+ return __cmd_buildid_list(file_name, argc, argv);
+#if defined(__i386__) || defined(__x86_64__)
else if (!strncmp(argv[0], "stat", 4))
- return kvm_cmd_stat(&kvm, argc, argv);
+ return kvm_cmd_stat(file_name, argc, argv);
+#endif
else
usage_with_options(kvm_usage, kvm_options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 484f26cc0c00..5acd6e8e658b 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -15,7 +15,7 @@
#include "util/thread_map.h"
#include "util/pmu.h"
#include "event-parse.h"
-#include "../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
#include <sys/mman.h>
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index c50985eaec41..238f923f2218 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -5,8 +5,9 @@ struct winsize;
void get_term_dimensions(struct winsize *ws);
+#include <asm/unistd.h>
+
#if defined(__i386__)
-#include "../../arch/x86/include/asm/unistd.h"
#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
#define cpu_relax() asm volatile("rep; nop" ::: "memory");
#define CPUINFO_PROC "model name"
@@ -16,7 +17,6 @@ void get_term_dimensions(struct winsize *ws);
#endif
#if defined(__x86_64__)
-#include "../../arch/x86/include/asm/unistd.h"
#define rmb() asm volatile("lfence" ::: "memory")
#define cpu_relax() asm volatile("rep; nop" ::: "memory");
#define CPUINFO_PROC "model name"
@@ -26,20 +26,17 @@ void get_term_dimensions(struct winsize *ws);
#endif
#ifdef __powerpc__
-#include "../../arch/powerpc/include/asm/unistd.h"
#define rmb() asm volatile ("sync" ::: "memory")
#define cpu_relax() asm volatile ("" ::: "memory");
#define CPUINFO_PROC "cpu"
#endif
#ifdef __s390__
-#include "../../arch/s390/include/asm/unistd.h"
#define rmb() asm volatile("bcr 15,0" ::: "memory")
#define cpu_relax() asm volatile("" ::: "memory");
#endif
#ifdef __sh__
-#include "../../arch/sh/include/asm/unistd.h"
#if defined(__SH4A__) || defined(__SH5__)
# define rmb() asm volatile("synco" ::: "memory")
#else
@@ -50,35 +47,30 @@ void get_term_dimensions(struct winsize *ws);
#endif
#ifdef __hppa__
-#include "../../arch/parisc/include/asm/unistd.h"
#define rmb() asm volatile("" ::: "memory")
#define cpu_relax() asm volatile("" ::: "memory");
#define CPUINFO_PROC "cpu"
#endif
#ifdef __sparc__
-#include "../../arch/sparc/include/uapi/asm/unistd.h"
#define rmb() asm volatile("":::"memory")
#define cpu_relax() asm volatile("":::"memory")
#define CPUINFO_PROC "cpu"
#endif
#ifdef __alpha__
-#include "../../arch/alpha/include/asm/unistd.h"
#define rmb() asm volatile("mb" ::: "memory")
#define cpu_relax() asm volatile("" ::: "memory")
#define CPUINFO_PROC "cpu model"
#endif
#ifdef __ia64__
-#include "../../arch/ia64/include/asm/unistd.h"
#define rmb() asm volatile ("mf" ::: "memory")
#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
#define CPUINFO_PROC "model name"
#endif
#ifdef __arm__
-#include "../../arch/arm/include/asm/unistd.h"
/*
* Use the __kuser_memory_barrier helper in the CPU helper page. See
* arch/arm/kernel/entry-armv.S in the kernel source for details.
@@ -89,13 +81,11 @@ void get_term_dimensions(struct winsize *ws);
#endif
#ifdef __aarch64__
-#include "../../arch/arm64/include/asm/unistd.h"
#define rmb() asm volatile("dmb ld" ::: "memory")
#define cpu_relax() asm volatile("yield" ::: "memory")
#endif
#ifdef __mips__
-#include "../../arch/mips/include/asm/unistd.h"
#define rmb() asm volatile( \
".set mips2\n\t" \
"sync\n\t" \
@@ -112,7 +102,7 @@ void get_term_dimensions(struct winsize *ws);
#include <sys/types.h>
#include <sys/syscall.h>
-#include "../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
#include "util/types.h"
#include <stdbool.h>
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 618d41140abd..d144d464ce39 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -18,8 +18,8 @@
#include "cpumap.h"
#include "thread_map.h"
#include "target.h"
-#include "../../../include/linux/hw_breakpoint.h"
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
#include "perf_regs.h"
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6f94d6dea00f..d99b476ef37c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -3,7 +3,8 @@
#include <linux/list.h>
#include <stdbool.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <stddef.h>
+#include <linux/perf_event.h>
#include "types.h"
#include "xyarray.h"
#include "cgroup.h"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7daad237dea5..566b84c695c8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1378,6 +1378,8 @@ static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
str = tmp + 1;
fprintf(fp, "# node%u cpu list : %s\n", c, str);
+
+ str += strlen(str) + 1;
}
return;
error:
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 879d215cdac9..9bc00783f24f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,7 +1,7 @@
#ifndef __PERF_HEADER_H
#define __PERF_HEADER_H
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
#include <sys/types.h>
#include <stdbool.h>
#include "types.h"
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index 516ecd9ddd6e..6ef213b35ecd 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -3,7 +3,7 @@
#include "evsel.h"
#include "evlist.h"
#include "sysfs.h"
-#include "../../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
#define TEST_ASSERT_VAL(text, cond) \
do { \
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 75c7b0fca6d9..6b6d03e93c3d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,4 @@
-#include "../../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
#include "util.h"
#include "../perf.h"
#include "evlist.h"
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 839230ceb18b..2820c407adb2 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -7,7 +7,7 @@
#include <linux/list.h>
#include <stdbool.h>
#include "types.h"
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
#include "types.h"
struct list_head;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 39f3abac7744..fdeb8ac7c5d2 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -2,7 +2,7 @@
#define __PMU_H
#include <linux/bitops.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
enum {
PERF_PMU_FORMAT_VALUE_CONFIG,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dd6426163ba6..0eae00ad5fe7 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,7 +7,7 @@
#include "symbol.h"
#include "thread.h"
#include <linux/rbtree.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
struct sample_queue;
struct ip_callchain;
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 2eeb51baf077..cfa906882e2c 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -90,17 +90,17 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
if (!strbuf_avail(sb))
strbuf_grow(sb, 64);
va_start(ap, fmt);
- len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+ len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
va_end(ap);
if (len < 0)
- die("your vscnprintf is broken");
+ die("your vsnprintf is broken");
if (len > strbuf_avail(sb)) {
strbuf_grow(sb, len);
va_start(ap, fmt);
- len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+ len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
va_end(ap);
if (len > strbuf_avail(sb)) {
- die("this should not happen, your snprintf is broken");
+ die("this should not happen, your vsnprintf is broken");
}
}
strbuf_setlen(sb, sb->len + len);
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
index 8a83dd2ffc11..d42073f12609 100644
--- a/tools/power/cpupower/.gitignore
+++ b/tools/power/cpupower/.gitignore
@@ -20,3 +20,10 @@ utils/cpufreq-set.o
utils/cpufreq-aperf.o
cpupower
bench/cpufreq-bench
+debug/kernel/Module.symvers
+debug/i386/centrino-decode
+debug/i386/dump_psb
+debug/i386/intel_gsic
+debug/i386/powernow-k8-decode
+debug/x86_64/centrino-decode
+debug/x86_64/powernow-k8-decode
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index cf397bd26d0c..d875a74a3bdf 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -253,7 +253,8 @@ clean:
| xargs rm -f
-rm -f $(OUTPUT)cpupower
-rm -f $(OUTPUT)libcpupower.so*
- -rm -rf $(OUTPUT)po/*.{gmo,pot}
+ -rm -rf $(OUTPUT)po/*.gmo
+ -rm -rf $(OUTPUT)po/*.pot
$(MAKE) -C bench O=$(OUTPUT) clean
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
index 3ba158f0e287..c05cc0ac80c7 100644
--- a/tools/power/cpupower/debug/i386/Makefile
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -26,7 +26,10 @@ $(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
clean:
- rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode}
+ rm -rf $(OUTPUT)centrino-decode
+ rm -rf $(OUTPUT)dump_psb
+ rm -rf $(OUTPUT)intel_gsic
+ rm -rf $(OUTPUT)powernow-k8-decode
install:
$(INSTALL) -d $(DESTDIR)${bindir}
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
index 1141c2073719..e01c35d13b6e 100644
--- a/tools/power/cpupower/man/cpupower-monitor.1
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -7,11 +7,11 @@ cpupower\-monitor \- Report processor frequency and idle statistics
.RB "\-l"
.B cpupower monitor
-.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB [ -c ] [ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB [ "\-i seconds" ]
.br
.B cpupower monitor
-.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB [ -c ][ "\-m <mon1>," [ "<mon2>,..." ] ]
.RB command
.br
.SH DESCRIPTION
@@ -64,6 +64,17 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option
Measure intervall.
.RE
.PP
+\-c
+.RS 4
+Schedule the process on every core before starting and ending measuring.
+This could be needed for the Idle_Stats monitor when no other MSR based
+monitor (has to be run on the core that is measured) is run in parallel.
+This is to wake up the processors from deeper sleep states and let the
+kernel re
+-account its cpuidle (C-state) information before reading the
+cpuidle timings from sysfs.
+.RE
+.PP
command
.RS 4
Measure idle and frequency characteristics of an arbitrary command/workload.
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 906895d21cce..93b0aa74ca03 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -158,6 +158,8 @@ out:
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
+ case 0x3A: /* IVB */
+ case 0x3E: /* IVB Xeon */
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
break;
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 2eb584cf2f55..aa9e95486a2d 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -92,6 +92,14 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
extern struct cpupower_cpu_info cpupower_cpu_info;
/* cpuid and cpuinfo helpers **************************/
+struct cpuid_core_info {
+ int pkg;
+ int core;
+ int cpu;
+
+ /* flags */
+ unsigned int is_online:1;
+};
/* CPU topology/hierarchy parsing ******************/
struct cpupower_topology {
@@ -101,18 +109,12 @@ struct cpupower_topology {
unsigned int threads; /* per core */
/* Array gets mallocated with cores entries, holding per core info */
- struct {
- int pkg;
- int core;
- int cpu;
-
- /* flags */
- unsigned int is_online:1;
- } *core_info;
+ struct cpuid_core_info *core_info;
};
extern int get_cpu_topology(struct cpupower_topology *cpu_top);
extern void cpu_topology_release(struct cpupower_topology cpu_top);
+
/* CPU topology/hierarchy parsing ******************/
/* X86 ONLY ****************************************/
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
index 96e28c124b5c..38ab91629463 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.c
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -37,25 +37,6 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
return (unsigned int) numread;
}
-static unsigned int sysfs_write_file(const char *path,
- const char *value, size_t len)
-{
- int fd;
- ssize_t numwrite;
-
- fd = open(path, O_WRONLY);
- if (fd == -1)
- return 0;
-
- numwrite = write(fd, value, len);
- if (numwrite < 1) {
- close(fd);
- return 0;
- }
- close(fd);
- return (unsigned int) numwrite;
-}
-
/*
* Detect whether a CPU is online
*
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index 4eae2c47ba48..c13120af519b 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -20,9 +20,8 @@
#include <helpers/sysfs.h>
/* returns -1 on failure, 0 on success */
-int sysfs_topology_read_file(unsigned int cpu, const char *fname)
+static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
{
- unsigned long value;
char linebuf[MAX_LINE_LEN];
char *endp;
char path[SYSFS_PATH_MAX];
@@ -31,20 +30,12 @@ int sysfs_topology_read_file(unsigned int cpu, const char *fname)
cpu, fname);
if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
return -1;
- value = strtoul(linebuf, &endp, 0);
+ *result = strtol(linebuf, &endp, 0);
if (endp == linebuf || errno == ERANGE)
return -1;
- return value;
+ return 0;
}
-struct cpuid_core_info {
- unsigned int pkg;
- unsigned int thread;
- unsigned int cpu;
- /* flags */
- unsigned int is_online:1;
-};
-
static int __compare(const void *t1, const void *t2)
{
struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
@@ -53,9 +44,9 @@ static int __compare(const void *t1, const void *t2)
return -1;
else if (top1->pkg > top2->pkg)
return 1;
- else if (top1->thread < top2->thread)
+ else if (top1->core < top2->core)
return -1;
- else if (top1->thread > top2->thread)
+ else if (top1->core > top2->core)
return 1;
else if (top1->cpu < top2->cpu)
return -1;
@@ -73,28 +64,42 @@ static int __compare(const void *t1, const void *t2)
*/
int get_cpu_topology(struct cpupower_topology *cpu_top)
{
- int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
+ int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
- cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
+ cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
if (cpu_top->core_info == NULL)
return -ENOMEM;
cpu_top->pkgs = cpu_top->cores = 0;
for (cpu = 0; cpu < cpus; cpu++) {
cpu_top->core_info[cpu].cpu = cpu;
cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
- cpu_top->core_info[cpu].pkg =
- sysfs_topology_read_file(cpu, "physical_package_id");
- if ((int)cpu_top->core_info[cpu].pkg != -1 &&
- cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
- cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
- cpu_top->core_info[cpu].core =
- sysfs_topology_read_file(cpu, "core_id");
+ if(sysfs_topology_read_file(
+ cpu,
+ "physical_package_id",
+ &(cpu_top->core_info[cpu].pkg)) < 0)
+ return -1;
+ if(sysfs_topology_read_file(
+ cpu,
+ "core_id",
+ &(cpu_top->core_info[cpu].core)) < 0)
+ return -1;
}
- cpu_top->pkgs++;
qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
__compare);
+ /* Count the number of distinct pkgs values. This works
+ because the primary sort of the core_info struct was just
+ done by pkg value. */
+ last_pkg = cpu_top->core_info[0].pkg;
+ for(cpu = 1; cpu < cpus; cpu++) {
+ if(cpu_top->core_info[cpu].pkg != last_pkg) {
+ last_pkg = cpu_top->core_info[cpu].pkg;
+ cpu_top->pkgs++;
+ }
+ }
+ cpu_top->pkgs++;
+
/* Intel's cores count is not consecutively numbered, there may
* be a core_id of 3, but none of 2. Assume there always is 0
* Get amount of cores by counting duplicates in a package
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 0d6571e418db..c4bae9203a69 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -39,6 +39,7 @@ static int mode;
static int interval = 1;
static char *show_monitors_param;
static struct cpupower_topology cpu_top;
+static unsigned int wake_cpus;
/* ToDo: Document this in the manpage */
static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
@@ -84,7 +85,7 @@ int fill_string_with_spaces(char *s, int n)
void print_header(int topology_depth)
{
int unsigned mon;
- int state, need_len, pr_mon_len;
+ int state, need_len;
cstate_t s;
char buf[128] = "";
int percent_width = 4;
@@ -93,7 +94,6 @@ void print_header(int topology_depth)
printf("%s|", buf);
for (mon = 0; mon < avail_monitors; mon++) {
- pr_mon_len = 0;
need_len = monitors[mon]->hw_states_num * (percent_width + 3)
- 1;
if (mon != 0) {
@@ -315,16 +315,28 @@ int fork_it(char **argv)
int do_interval_measure(int i)
{
unsigned int num;
+ int cpu;
+
+ if (wake_cpus)
+ for (cpu = 0; cpu < cpu_count; cpu++)
+ bind_cpu(cpu);
for (num = 0; num < avail_monitors; num++) {
dprint("HW C-state residency monitor: %s - States: %d\n",
monitors[num]->name, monitors[num]->hw_states_num);
monitors[num]->start();
}
+
sleep(i);
+
+ if (wake_cpus)
+ for (cpu = 0; cpu < cpu_count; cpu++)
+ bind_cpu(cpu);
+
for (num = 0; num < avail_monitors; num++)
monitors[num]->stop();
+
return 0;
}
@@ -333,7 +345,7 @@ static void cmdline(int argc, char *argv[])
int opt;
progname = basename(argv[0]);
- while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
+ while ((opt = getopt(argc, argv, "+lci:m:")) != -1) {
switch (opt) {
case 'l':
if (mode)
@@ -352,6 +364,9 @@ static void cmdline(int argc, char *argv[])
mode = show;
show_monitors_param = optarg;
break;
+ case 'c':
+ wake_cpus = 1;
+ break;
default:
print_wrong_arg_exit();
}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
index 9312ee1f2dbc..9e43f3371fbc 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -65,4 +65,21 @@ extern long long timespec_diff_us(struct timespec start, struct timespec end);
"could be inaccurate\n"), mes, ov); \
}
+
+/* Taken over from x86info project sources -> return 0 on success */
+#include <sched.h>
+#include <sys/types.h>
+#include <unistd.h>
+static inline int bind_cpu(int cpu)
+{
+ cpu_set_t set;
+
+ if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
+ CPU_ZERO(&set);
+ CPU_SET(cpu, &set);
+ return sched_setaffinity(getpid(), sizeof(set), &set);
+ }
+ return 1;
+}
+
#endif /* __CPUIDLE_INFO_HW__ */
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
index a1bc07cd53e1..a99b43b97d6d 100644
--- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -150,9 +150,15 @@ static struct cpuidle_monitor *snb_register(void)
|| cpupower_cpu_info.family != 6)
return NULL;
- if (cpupower_cpu_info.model != 0x2A
- && cpupower_cpu_info.model != 0x2D)
+ switch (cpupower_cpu_info.model) {
+ case 0x2A: /* SNB */
+ case 0x2D: /* SNB Xeon */
+ case 0x3A: /* IVB */
+ case 0x3E: /* IVB Xeon */
+ break;
+ default:
return NULL;
+ }
is_valid = calloc(cpu_count, sizeof(int));
for (num = 0; num < SNB_CSTATE_COUNT; num++) {
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 96ce80a3743b..2964b96aa55f 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -1,8 +1,11 @@
-ifeq ("$(origin O)", "command line")
+ifeq ($(origin O), command line)
dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
ABSOLUTE_O := $(shell cd $(O) ; pwd)
- OUTPUT := $(ABSOLUTE_O)/
+ OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
COMMAND_O := O=$(ABSOLUTE_O)
+ifeq ($(objtree),)
+ objtree := $(O)
+endif
endif
ifneq ($(OUTPUT),)
@@ -41,7 +44,16 @@ else
NO_SUBDIR = :
endif
-QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
+#
+# Define a callable command for descending to a new directory
+#
+# Call by doing: $(call descend,directory[,target])
+#
+descend = \
+ +mkdir -p $(OUTPUT)$(1) && \
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
+
+QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
ifneq ($(findstring $(MAKEFLAGS),s),s)
@@ -56,5 +68,10 @@ ifndef V
$(MAKE) $(PRINT_DIR) -C $$subdir
QUIET_FLEX = @echo ' ' FLEX $@;
QUIET_BISON = @echo ' ' BISON $@;
+
+ descend = \
+ @echo ' ' DESCEND $(1); \
+ mkdir -p $(OUTPUT)$(1) && \
+ $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
endif
endif